1 From 041cf8356a4eb91ee8118004b2bc9c78cdd7866c Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Mon, 20 Jan 2014 15:52:07 +0100
4 Subject: [PATCH] ahci-platform: "Library-ise" suspend / resume functionality
6 Split suspend / resume code into host suspend / resume functionality and
7 resource enable / disabling phases, and export the new suspend_ / resume_host
10 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
12 drivers/ata/ahci_platform.c | 109 ++++++++++++++++++++++++++++++++++++------
13 include/linux/ahci_platform.h | 5 ++
14 2 files changed, 99 insertions(+), 15 deletions(-)
16 diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
17 index 7f3f2ac..bdadec1 100644
18 --- a/drivers/ata/ahci_platform.c
19 +++ b/drivers/ata/ahci_platform.c
20 @@ -452,14 +452,26 @@ static void ahci_host_stop(struct ata_host *host)
23 #ifdef CONFIG_PM_SLEEP
24 -static int ahci_suspend(struct device *dev)
26 + * ahci_platform_suspend_host - Suspend an ahci-platform host
27 + * @dev: device pointer for the host
29 + * This function does all the usual steps needed to suspend an
30 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
31 + * must be disabled after calling this.
37 + * 0 on success otherwise a negative error code
39 +int ahci_platform_suspend_host(struct device *dev)
41 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
42 struct ata_host *host = dev_get_drvdata(dev);
43 struct ahci_host_priv *hpriv = host->private_data;
44 void __iomem *mmio = hpriv->mmio;
48 if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
49 dev_err(dev, "firmware update required for suspend/resume\n");
50 @@ -476,7 +488,64 @@ static int ahci_suspend(struct device *dev)
51 writel(ctl, mmio + HOST_CTL);
52 readl(mmio + HOST_CTL); /* flush */
54 - rc = ata_host_suspend(host, PMSG_SUSPEND);
55 + return ata_host_suspend(host, PMSG_SUSPEND);
57 +EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
60 + * ahci_platform_resume_host - Resume an ahci-platform host
61 + * @dev: device pointer for the host
63 + * This function does all the usual steps needed to resume an
64 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
65 + * must be initialized / enabled before calling this.
71 + * 0 on success otherwise a negative error code
73 +int ahci_platform_resume_host(struct device *dev)
75 + struct ata_host *host = dev_get_drvdata(dev);
78 + if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
79 + rc = ahci_reset_controller(host);
83 + ahci_init_controller(host);
86 + ata_host_resume(host);
90 +EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
93 + * ahci_platform_suspend - Suspend an ahci-platform device
94 + * @dev: the platform device to suspend
96 + * This function suspends the host associated with the device, followed
97 + * by disabling all the resources of the device.
103 + * 0 on success otherwise a negative error code
105 +int ahci_platform_suspend(struct device *dev)
107 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
108 + struct ata_host *host = dev_get_drvdata(dev);
109 + struct ahci_host_priv *hpriv = host->private_data;
112 + rc = ahci_platform_suspend_host(dev);
116 @@ -487,8 +556,22 @@ static int ahci_suspend(struct device *dev)
120 +EXPORT_SYMBOL_GPL(ahci_platform_suspend);
122 -static int ahci_resume(struct device *dev)
124 + * ahci_platform_resume - Resume an ahci-platform device
125 + * @dev: the platform device to resume
127 + * This function enables all the resources of the device followed by
128 + * resuming the host associated with the device.
134 + * 0 on success otherwise a negative error code
136 +int ahci_platform_resume(struct device *dev)
138 struct ahci_platform_data *pdata = dev_get_platdata(dev);
139 struct ata_host *host = dev_get_drvdata(dev);
140 @@ -505,15 +588,9 @@ static int ahci_resume(struct device *dev)
141 goto disable_resources;
144 - if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
145 - rc = ahci_reset_controller(host);
147 - goto disable_resources;
149 - ahci_init_controller(host);
152 - ata_host_resume(host);
153 + rc = ahci_platform_resume_host(dev);
155 + goto disable_resources;
159 @@ -522,9 +599,11 @@ static int ahci_resume(struct device *dev)
163 +EXPORT_SYMBOL_GPL(ahci_platform_resume);
166 -static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
167 +static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
168 + ahci_platform_resume);
170 static const struct of_device_id ahci_of_match[] = {
171 { .compatible = "snps,spear-ahci", },
172 diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
173 index b80c51c..542f268 100644
174 --- a/include/linux/ahci_platform.h
175 +++ b/include/linux/ahci_platform.h
176 @@ -50,4 +50,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
177 unsigned int force_port_map,
178 unsigned int mask_port_map);
180 +int ahci_platform_suspend_host(struct device *dev);
181 +int ahci_platform_resume_host(struct device *dev);
182 +int ahci_platform_suspend(struct device *dev);
183 +int ahci_platform_resume(struct device *dev);
185 #endif /* _AHCI_PLATFORM_H */