On Dec 21, 2011, at 1:10 AM, Jia Hongtao wrote: > 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> > --- > arch/powerpc/include/asm/pci-bridge.h | 6 ++ > arch/powerpc/sysdev/fsl_pci.c | 108 +++++++++++++++++++++++++++++++++ > 2 files changed, 114 insertions(+), 0 deletions(-) > > diff --git a/arch/powerpc/include/asm/pci-bridge.h > b/arch/powerpc/include/asm/pci-bridge.h > index 882b6aa..c99b40e 100644 > --- a/arch/powerpc/include/asm/pci-bridge.h > +++ b/arch/powerpc/include/asm/pci-bridge.h > @@ -92,6 +92,12 @@ struct pci_controller { > > void *private_data; > #endif /* CONFIG_PPC64 */ > + > +#ifdef CONFIG_SUSPEND > + struct pci_outbound_window_regs __iomem *pci_pow; > + struct pci_inbound_window_regs __iomem *pci_piw;
Why do we need both pointers, we dont you just keep a pointer to 'struct ccsr_pci __iomem' ? Also, is there really a significant speed difference that we need to cache the ioremap pointer? Can we not just do the ioremap() both in suspend & resume functions? > + void *saved_regs; > +#endif Should we just put this under private_data and expose that everywhere (ie not just on PPC64) > }; Also, dont we need to save/restore the setting of PCSRBAR/PEXCSRBAR > > /* 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 e318e9d..046866f 100644 > --- a/arch/powerpc/sysdev/fsl_pci.c > +++ b/arch/powerpc/sysdev/fsl_pci.c > @@ -756,12 +756,120 @@ static int __devinit fsl_pci_probe(struct > platform_device *pdev) > return 0; > } > > +#ifdef CONFIG_SUSPEND > + > +#define PCI_POW_NUMBER 5 > +#define PCI_POW_BIAS 0xc00 > +#define PCI_PIW_NUMBER 3 > +#define PCI_PIW_BIAS 0xda0 > + > +static int fsl_pci_suspend(struct platform_device *dev, pm_message_t state) > +{ > + struct pci_controller *hose; > + struct pci_outbound_window_regs *pci_saved_pow; > + struct pci_inbound_window_regs *pci_saved_piw; > + struct resource pci_rsrc; > + unsigned int i; > + > + hose = pci_find_hose_for_OF_device(dev->dev.of_node); > + of_address_to_resource(dev->dev.of_node, 0, &pci_rsrc); > + > + hose->pci_pow = ioremap(pci_rsrc.start + PCI_POW_BIAS, > + sizeof(struct pci_outbound_window_regs) > + * PCI_POW_NUMBER); > + if (!hose->pci_pow) { > + pr_err("pci_pow ioremap error!\n"); > + return -ENOMEM; > + } > + > + hose->pci_piw = ioremap(pci_rsrc.start + PCI_PIW_BIAS, > + sizeof(struct pci_inbound_window_regs) > + * PCI_PIW_NUMBER); > + if (!hose->pci_piw) { > + pr_err("pci_piw ioremap error!\n"); > + goto err1; > + } > + > + hose->saved_regs = kmalloc( > + sizeof(struct pci_outbound_window_regs) * PCI_POW_NUMBER + > + sizeof(struct pci_inbound_window_regs) * PCI_PIW_NUMBER, > + GFP_KERNEL); > + if (!hose->saved_regs) > + goto err2; > + > + pci_saved_pow = hose->saved_regs; > + for (i = 0; i < PCI_POW_NUMBER; i++) { > + pci_saved_pow[i].potar = in_be32(&hose->pci_pow[i].potar); > + pci_saved_pow[i].potear = in_be32(&hose->pci_pow[i].potear); > + pci_saved_pow[i].powbar = in_be32(&hose->pci_pow[i].powbar); > + pci_saved_pow[i].powar = in_be32(&hose->pci_pow[i].powar); > + } > + > + pci_saved_piw = (struct pci_inbound_window_regs *) > + (pci_saved_pow + PCI_POW_NUMBER); > + for (i = 0; i < PCI_PIW_NUMBER; i++) { > + pci_saved_piw[i].pitar = in_be32(&hose->pci_piw[i].pitar); > + pci_saved_piw[i].piwbar = in_be32(&hose->pci_piw[i].piwbar); > + pci_saved_piw[i].piwbear = in_be32(&hose->pci_piw[i].piwbear); > + pci_saved_piw[i].piwar = in_be32(&hose->pci_piw[i].piwar); > + } > + > + return 0; > + > +err2: > + iounmap(hose->pci_piw); > + > +err1: > + iounmap(hose->pci_pow); > + return -ENOMEM; > +} > + > +static int fsl_pci_resume(struct platform_device *dev) > +{ > + struct pci_controller *hose; > + struct pci_outbound_window_regs *pci_saved_pow; > + struct pci_inbound_window_regs *pci_saved_piw; > + unsigned int i; > + > + hose = pci_find_hose_for_OF_device(dev->dev.of_node); > + if (!hose->pci_pow || !hose->pci_piw || !hose->saved_regs) > + return 0; > + > + pci_saved_pow = hose->saved_regs; > + for (i = 0; i < PCI_POW_NUMBER; i++) { > + out_be32(&hose->pci_pow[i].potar, pci_saved_pow[i].potar); > + out_be32(&hose->pci_pow[i].potear, pci_saved_pow[i].potear); > + out_be32(&hose->pci_pow[i].powbar, pci_saved_pow[i].powbar); > + out_be32(&hose->pci_pow[i].powar, pci_saved_pow[i].powar); > + } > + iounmap(hose->pci_pow); > + > + pci_saved_piw = (struct pci_inbound_window_regs *) > + (pci_saved_pow + PCI_POW_NUMBER); > + for (i = 0; i < PCI_PIW_NUMBER; i++) { > + out_be32(&hose->pci_piw[i].pitar, pci_saved_piw[i].pitar); > + out_be32(&hose->pci_piw[i].piwbar, pci_saved_piw[i].piwbar); > + out_be32(&hose->pci_piw[i].piwbear, pci_saved_piw[i].piwbear); > + out_be32(&hose->pci_piw[i].piwar, pci_saved_piw[i].piwar); > + } > + iounmap(hose->pci_piw); > + kfree(hose->saved_regs); > + hose->saved_regs = 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 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev