From 8121ed9c7ea2d56f5e0a98c2db396214f85d7485 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 22 Feb 2014 16:53:35 +0100 Subject: [PATCH 115/182] 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. tj: Minor comment formatting updates. Signed-off-by: Hans de Goede Signed-off-by: Tejun Heo --- drivers/ata/ahci_platform.c | 97 ++++++++++++++++++++++++++++++++++------- include/linux/ahci_platform.h | 5 +++ 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 19e9eaa..01f7bbe 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -432,14 +432,23 @@ 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. + * + * 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"); @@ -456,7 +465,58 @@ 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. + * + * 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. + * + * 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; @@ -467,8 +527,19 @@ 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. + * + * 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); @@ -485,15 +556,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; @@ -502,9 +567,11 @@ disable_resources: 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.7.10.4