Re: [PATCH SDK1.2 3/3] powerpc/fsl-pci: Add pci inbound/outbound PM support
flat view
From: Kumar Gala <hidden>
Date: 2012-03-16 19:20:16
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. =20 Signed-off-by: Jiang Yutang <redacted> Signed-off-by: Jia Hongtao <redacted> Signed-off-by: Li Yang <redacted> --- arch/powerpc/include/asm/pci-bridge.h | 6 ++ arch/powerpc/sysdev/fsl_pci.c | 108 =
+++++++++++++++++++++++++++++++++
quoted hunk ↗ jump to hunk
2 files changed, 114 insertions(+), 0 deletions(-) =20diff --git a/arch/powerpc/include/asm/pci-bridge.h =
b/arch/powerpc/include/asm/pci-bridge.h
quoted hunk ↗ jump to hunk
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 {=20 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
quoted hunk ↗ jump to hunk
=20 /* These are used for config access before all the PCI probingdiff --git a/arch/powerpc/sysdev/fsl_pci.c =
b/arch/powerpc/sysdev/fsl_pci.c
quoted hunk ↗ jump to hunk
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; } =20 +#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)
quoted hunk ↗ jump to hunk
+{ + 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 =3D pci_find_hose_for_OF_device(dev->dev.of_node); + of_address_to_resource(dev->dev.of_node, 0, &pci_rsrc); + + hose->pci_pow =3D 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 =3D 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 =3D kmalloc( + sizeof(struct pci_outbound_window_regs) * PCI_POW_NUMBER =
+
quoted hunk ↗ jump to hunk
+ sizeof(struct pci_inbound_window_regs) * PCI_PIW_NUMBER, + GFP_KERNEL); + if (!hose->saved_regs) + goto err2; + + pci_saved_pow =3D hose->saved_regs; + for (i =3D 0; i < PCI_POW_NUMBER; i++) { + pci_saved_pow[i].potar =3D =
in_be32(&hose->pci_pow[i].potar);
+ pci_saved_pow[i].potear =3D =
in_be32(&hose->pci_pow[i].potear);
+ pci_saved_pow[i].powbar =3D =
in_be32(&hose->pci_pow[i].powbar);
+ pci_saved_pow[i].powar =3D =
in_be32(&hose->pci_pow[i].powar);
quoted hunk ↗ jump to hunk
+ } + + pci_saved_piw =3D (struct pci_inbound_window_regs *) + (pci_saved_pow + PCI_POW_NUMBER); + for (i =3D 0; i < PCI_PIW_NUMBER; i++) { + pci_saved_piw[i].pitar =3D =
in_be32(&hose->pci_piw[i].pitar);
+ pci_saved_piw[i].piwbar =3D =
in_be32(&hose->pci_piw[i].piwbar);
+ pci_saved_piw[i].piwbear =3D =
in_be32(&hose->pci_piw[i].piwbear);
+ pci_saved_piw[i].piwar =3D =
in_be32(&hose->pci_piw[i].piwar);
quoted hunk ↗ jump to hunk
+ } + + 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 =3D 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 =3D hose->saved_regs; + for (i =3D 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);
quoted hunk ↗ jump to hunk
+ } + iounmap(hose->pci_pow); + + pci_saved_piw =3D (struct pci_inbound_window_regs *) + (pci_saved_pow + PCI_POW_NUMBER); + for (i =3D 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 =3D NULL;
+
+ return 0;
+}
+#endif
+
static struct platform_driver fsl_pci_driver =3D {
.driver =3D {
.name =3D "fsl-pci",
.of_match_table =3D pci_ids,
},
.probe =3D fsl_pci_probe,
+#ifdef CONFIG_SUSPEND
+ .suspend =3D fsl_pci_suspend,
+ .resume =3D fsl_pci_resume,
+#endif
};
=20
static int __init fsl_pci_init(void)
--=20
1.7.5.1
=20
=20
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev