sunxi: driver refresh for 3.13
[openwrt/svn-archive/archive.git] / target / linux / sunxi / patches-3.13 / 160-9-ahci-plat-libraryise-suspend-resume.patch
diff --git a/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch b/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch
new file mode 100644 (file)
index 0000000..49ddac0
--- /dev/null
@@ -0,0 +1,188 @@
+From 041cf8356a4eb91ee8118004b2bc9c78cdd7866c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 20 Jan 2014 15:52:07 +0100
+Subject: [PATCH] ahci-platform: "Library-ise" suspend / resume functionality
+
+Split suspend / resume code into host suspend / resume functionality and
+resource enable / disabling phases, and export the new suspend_ / resume_host
+functions.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci_platform.c   | 109 ++++++++++++++++++++++++++++++++++++------
+ include/linux/ahci_platform.h |   5 ++
+ 2 files changed, 99 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 7f3f2ac..bdadec1 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -452,14 +452,26 @@ static void ahci_host_stop(struct ata_host *host)
+ }
+ #ifdef CONFIG_PM_SLEEP
+-static int ahci_suspend(struct device *dev)
++/**
++ *    ahci_platform_suspend_host - Suspend an ahci-platform host
++ *    @dev: device pointer for the host
++ *
++ *    This function does all the usual steps needed to suspend an
++ *    ahci-platform host, note any necessary resources (ie clks, phy, etc.)
++ *    must be disabled after calling this.
++ *
++ *    LOCKING:
++ *    None.
++ *
++ *    RETURNS:
++ *    0 on success otherwise a negative error code
++ */
++int ahci_platform_suspend_host(struct device *dev)
+ {
+-      struct ahci_platform_data *pdata = dev_get_platdata(dev);
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       void __iomem *mmio = hpriv->mmio;
+       u32 ctl;
+-      int rc;
+       if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
+               dev_err(dev, "firmware update required for suspend/resume\n");
+@@ -476,7 +488,64 @@ static int ahci_suspend(struct device *dev)
+       writel(ctl, mmio + HOST_CTL);
+       readl(mmio + HOST_CTL); /* flush */
+-      rc = ata_host_suspend(host, PMSG_SUSPEND);
++      return ata_host_suspend(host, PMSG_SUSPEND);
++}
++EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
++
++/**
++ *    ahci_platform_resume_host - Resume an ahci-platform host
++ *    @dev: device pointer for the host
++ *
++ *    This function does all the usual steps needed to resume an
++ *    ahci-platform host, note any necessary resources (ie clks, phy, etc.)
++ *    must be initialized / enabled before calling this.
++ *
++ *    LOCKING:
++ *    None.
++ *
++ *    RETURNS:
++ *    0 on success otherwise a negative error code
++ */
++int ahci_platform_resume_host(struct device *dev)
++{
++      struct ata_host *host = dev_get_drvdata(dev);
++      int rc;
++
++      if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
++              rc = ahci_reset_controller(host);
++              if (rc)
++                      return rc;
++
++              ahci_init_controller(host);
++      }
++
++      ata_host_resume(host);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
++
++/**
++ *    ahci_platform_suspend - Suspend an ahci-platform device
++ *    @dev: the platform device to suspend
++ *
++ *    This function suspends the host associated with the device, followed
++ *    by disabling all the resources of the device.
++ *
++ *    LOCKING:
++ *    None.
++ *
++ *    RETURNS:
++ *    0 on success otherwise a negative error code
++ */
++int ahci_platform_suspend(struct device *dev)
++{
++      struct ahci_platform_data *pdata = dev_get_platdata(dev);
++      struct ata_host *host = dev_get_drvdata(dev);
++      struct ahci_host_priv *hpriv = host->private_data;
++      int rc;
++
++      rc = ahci_platform_suspend_host(dev);
+       if (rc)
+               return rc;
+@@ -487,8 +556,22 @@ static int ahci_suspend(struct device *dev)
+       return 0;
+ }
++EXPORT_SYMBOL_GPL(ahci_platform_suspend);
+-static int ahci_resume(struct device *dev)
++/**
++ *    ahci_platform_resume - Resume an ahci-platform device
++ *    @dev: the platform device to resume
++ *
++ *    This function enables all the resources of the device followed by
++ *    resuming the host associated with the device.
++ *
++ *    LOCKING:
++ *    None.
++ *
++ *    RETURNS:
++ *    0 on success otherwise a negative error code
++ */
++int ahci_platform_resume(struct device *dev)
+ {
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
+       struct ata_host *host = dev_get_drvdata(dev);
+@@ -505,15 +588,9 @@ static int ahci_resume(struct device *dev)
+                       goto disable_resources;
+       }
+-      if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+-              rc = ahci_reset_controller(host);
+-              if (rc)
+-                      goto disable_resources;
+-
+-              ahci_init_controller(host);
+-      }
+-
+-      ata_host_resume(host);
++      rc = ahci_platform_resume_host(dev);
++      if (rc)
++              goto disable_resources;
+       return 0;
+@@ -522,9 +599,11 @@ static int ahci_resume(struct device *dev)
+       return rc;
+ }
++EXPORT_SYMBOL_GPL(ahci_platform_resume);
+ #endif
+-static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
++static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
++                       ahci_platform_resume);
+ static const struct of_device_id ahci_of_match[] = {
+       { .compatible = "snps,spear-ahci", },
+diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
+index b80c51c..542f268 100644
+--- a/include/linux/ahci_platform.h
++++ b/include/linux/ahci_platform.h
+@@ -50,4 +50,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
+                           unsigned int force_port_map,
+                           unsigned int mask_port_map);
++int ahci_platform_suspend_host(struct device *dev);
++int ahci_platform_resume_host(struct device *dev);
++int ahci_platform_suspend(struct device *dev);
++int ahci_platform_resume(struct device *dev);
++
+ #endif /* _AHCI_PLATFORM_H */
+-- 
+1.8.5.5
+