summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/omap-iommu.c
diff options
context:
space:
mode:
authorSuman Anna <s-anna@ti.com>2019-08-07 10:26:49 +0200
committerJoerg Roedel <jroedel@suse.de>2019-08-09 17:37:10 +0200
commitc4206c4e190bd272e4e86389613f2cded4609ba1 (patch)
treec4e7c5e2ca3b922d04eacf40899def6a86b6f6fe /drivers/iommu/omap-iommu.c
parentiommu/omap: add logic to save/restore locked TLBs (diff)
downloadlinux-c4206c4e190bd272e4e86389613f2cded4609ba1.tar.xz
linux-c4206c4e190bd272e4e86389613f2cded4609ba1.zip
iommu/omap: Add system suspend/resume support
The MMU registers for the remote processors lose their context in Open Switch Retention (OSWR) or device OFF modes. Hence, the context of the IOMMU needs to be saved before it is put into any of these lower power state (OSWR/OFF) and restored before it is powered up to ON again. The IOMMUs need to be active as long as the client devices that are present behind the IOMMU are active. This patch adds the dev_pm_ops callbacks to provide the system suspend/resume functionality through the appropriate runtime PM callbacks. The PM runtime_resume and runtime_suspend callbacks are already used to enable, configure and disable the IOMMUs during the attaching and detaching of the client devices to the IOMMUs, and the new PM callbacks reuse the same code by invoking the pm_runtime_force_suspend() and pm_runtime_force_resume() API. The functionality in dev_pm_ops .prepare() checks if the IOMMU device was already runtime suspended, and skips invoking the suspend/resume PM callbacks. The suspend/resume PM callbacks are plugged in through the 'late' pm ops to ensure that the IOMMU devices will be suspended only after its master devices (remoteproc devices) are suspended and restored before them. NOTE: There are two other existing API, omap_iommu_save_ctx() and omap_iommu_restore_ctx(). These are left as is to support suspend/resume of devices on legacy OMAP3 SoC. Signed-off-by: Suman Anna <s-anna@ti.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/omap-iommu.c')
-rw-r--r--drivers/iommu/omap-iommu.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 7640f2bd7c81..ef62ac9057bb 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -65,6 +65,9 @@ static struct omap_iommu_domain *to_omap_domain(struct iommu_domain *dom)
/**
* omap_iommu_save_ctx - Save registers for pm off-mode support
* @dev: client device
+ *
+ * This should be treated as an deprecated API. It is preserved only
+ * to maintain existing functionality for OMAP3 ISP driver.
**/
void omap_iommu_save_ctx(struct device *dev)
{
@@ -92,6 +95,9 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
/**
* omap_iommu_restore_ctx - Restore registers for pm off-mode support
* @dev: client device
+ *
+ * This should be treated as an deprecated API. It is preserved only
+ * to maintain existing functionality for OMAP3 ISP driver.
**/
void omap_iommu_restore_ctx(struct device *dev)
{
@@ -1021,6 +1027,23 @@ static int omap_iommu_runtime_resume(struct device *dev)
return ret;
}
+/**
+ * omap_iommu_suspend_prepare - prepare() dev_pm_ops implementation
+ * @dev: iommu device
+ *
+ * This function performs the necessary checks to determine if the IOMMU
+ * device needs suspending or not. The function checks if the runtime_pm
+ * status of the device is suspended, and returns 1 in that case. This
+ * results in the PM core to skip invoking any of the Sleep PM callbacks
+ * (suspend, suspend_late, resume, resume_early etc).
+ */
+static int omap_iommu_prepare(struct device *dev)
+{
+ if (pm_runtime_status_suspended(dev))
+ return 1;
+ return 0;
+}
+
static bool omap_iommu_can_register(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1198,6 +1221,9 @@ static int omap_iommu_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops omap_iommu_pm_ops = {
+ .prepare = omap_iommu_prepare,
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
omap_iommu_runtime_resume, NULL)
};