diff options
author | Andiry Xu <andiry.xu@amd.com> | 2010-10-14 10:23:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:22:13 -0400 |
commit | 5535b1d5f8885695c6ded783c692e3c0d0eda8ca (patch) | |
tree | f5454493a1c50e4a6254d904578dc3ecfd1d6e63 /drivers/usb/host/xhci-pci.c | |
parent | 9777e3ce907d4cb5a513902a87ecd03b52499569 (diff) |
USB: xHCI: PCI power management implementation
This patch implements the PCI suspend/resume.
Please refer to xHCI spec for doing the suspend/resume operation.
For S3, CSS/SRS in USBCMD is used to save/restore the internal state.
However, an error maybe occurs while restoring the internal state.
In this case, it means that HC internal state is wrong and HC will be
re-initialized.
Signed-off-by: Libin Yang <libin.yang@amd.com>
Signed-off-by: Dong Nguyen <dong.nguyen@amd.com>
Signed-off-by: Andiry Xu <andiry.xu@amd.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-pci.c')
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 3865f8c6f647..bb668a894ab9 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
@@ -116,6 +116,30 @@ static int xhci_pci_setup(struct usb_hcd *hcd) | |||
116 | return xhci_pci_reinit(xhci, pdev); | 116 | return xhci_pci_reinit(xhci, pdev); |
117 | } | 117 | } |
118 | 118 | ||
119 | #ifdef CONFIG_PM | ||
120 | static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) | ||
121 | { | ||
122 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
123 | int retval = 0; | ||
124 | |||
125 | if (hcd->state != HC_STATE_SUSPENDED) | ||
126 | return -EINVAL; | ||
127 | |||
128 | retval = xhci_suspend(xhci); | ||
129 | |||
130 | return retval; | ||
131 | } | ||
132 | |||
133 | static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) | ||
134 | { | ||
135 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
136 | int retval = 0; | ||
137 | |||
138 | retval = xhci_resume(xhci, hibernated); | ||
139 | return retval; | ||
140 | } | ||
141 | #endif /* CONFIG_PM */ | ||
142 | |||
119 | static const struct hc_driver xhci_pci_hc_driver = { | 143 | static const struct hc_driver xhci_pci_hc_driver = { |
120 | .description = hcd_name, | 144 | .description = hcd_name, |
121 | .product_desc = "xHCI Host Controller", | 145 | .product_desc = "xHCI Host Controller", |
@@ -132,7 +156,10 @@ static const struct hc_driver xhci_pci_hc_driver = { | |||
132 | */ | 156 | */ |
133 | .reset = xhci_pci_setup, | 157 | .reset = xhci_pci_setup, |
134 | .start = xhci_run, | 158 | .start = xhci_run, |
135 | /* suspend and resume implemented later */ | 159 | #ifdef CONFIG_PM |
160 | .pci_suspend = xhci_pci_suspend, | ||
161 | .pci_resume = xhci_pci_resume, | ||
162 | #endif | ||
136 | .stop = xhci_stop, | 163 | .stop = xhci_stop, |
137 | .shutdown = xhci_shutdown, | 164 | .shutdown = xhci_shutdown, |
138 | 165 | ||
@@ -188,6 +215,11 @@ static struct pci_driver xhci_pci_driver = { | |||
188 | /* suspend and resume implemented later */ | 215 | /* suspend and resume implemented later */ |
189 | 216 | ||
190 | .shutdown = usb_hcd_pci_shutdown, | 217 | .shutdown = usb_hcd_pci_shutdown, |
218 | #ifdef CONFIG_PM_SLEEP | ||
219 | .driver = { | ||
220 | .pm = &usb_hcd_pci_pm_ops | ||
221 | }, | ||
222 | #endif | ||
191 | }; | 223 | }; |
192 | 224 | ||
193 | int xhci_register_pci(void) | 225 | int xhci_register_pci(void) |