aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci_platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ahci_platform.c')
-rw-r--r--drivers/ata/ahci_platform.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 43b875810d1b..48be4e189163 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -202,6 +202,71 @@ static int __devexit ahci_remove(struct platform_device *pdev)
202 return 0; 202 return 0;
203} 203}
204 204
205#ifdef CONFIG_PM
206static int ahci_suspend(struct device *dev)
207{
208 struct ahci_platform_data *pdata = dev_get_platdata(dev);
209 struct ata_host *host = dev_get_drvdata(dev);
210 struct ahci_host_priv *hpriv = host->private_data;
211 void __iomem *mmio = hpriv->mmio;
212 u32 ctl;
213 int rc;
214
215 if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
216 dev_err(dev, "firmware update required for suspend/resume\n");
217 return -EIO;
218 }
219
220 /*
221 * AHCI spec rev1.1 section 8.3.3:
222 * Software must disable interrupts prior to requesting a
223 * transition of the HBA to D3 state.
224 */
225 ctl = readl(mmio + HOST_CTL);
226 ctl &= ~HOST_IRQ_EN;
227 writel(ctl, mmio + HOST_CTL);
228 readl(mmio + HOST_CTL); /* flush */
229
230 rc = ata_host_suspend(host, PMSG_SUSPEND);
231 if (rc)
232 return rc;
233
234 if (pdata && pdata->suspend)
235 return pdata->suspend(dev);
236 return 0;
237}
238
239static int ahci_resume(struct device *dev)
240{
241 struct ahci_platform_data *pdata = dev_get_platdata(dev);
242 struct ata_host *host = dev_get_drvdata(dev);
243 int rc;
244
245 if (pdata && pdata->resume) {
246 rc = pdata->resume(dev);
247 if (rc)
248 return rc;
249 }
250
251 if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
252 rc = ahci_reset_controller(host);
253 if (rc)
254 return rc;
255
256 ahci_init_controller(host);
257 }
258
259 ata_host_resume(host);
260
261 return 0;
262}
263
264static struct dev_pm_ops ahci_pm_ops = {
265 .suspend = &ahci_suspend,
266 .resume = &ahci_resume,
267};
268#endif
269
205static const struct of_device_id ahci_of_match[] = { 270static const struct of_device_id ahci_of_match[] = {
206 { .compatible = "calxeda,hb-ahci", }, 271 { .compatible = "calxeda,hb-ahci", },
207 {}, 272 {},
@@ -214,6 +279,9 @@ static struct platform_driver ahci_driver = {
214 .name = "ahci", 279 .name = "ahci",
215 .owner = THIS_MODULE, 280 .owner = THIS_MODULE,
216 .of_match_table = ahci_of_match, 281 .of_match_table = ahci_of_match,
282#ifdef CONFIG_PM
283 .pm = &ahci_pm_ops,
284#endif
217 }, 285 },
218 .id_table = ahci_devtype, 286 .id_table = ahci_devtype,
219}; 287};