summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/Makefile2
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c43
-rw-r--r--drivers/iommu/omap-iommu.c17
-rw-r--r--drivers/iommu/omap-iommu.h2
-rw-r--r--include/linux/platform_data/iommu-omap.h2
5 files changed, 66 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 600650551621..d4f11c5070ae 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -229,3 +229,5 @@ include/generated/ti-pm-asm-offsets.h: arch/arm/mach-omap2/pm-asm-offsets.s FORC
$(obj)/sleep33xx.o $(obj)/sleep43xx.o: include/generated/ti-pm-asm-offsets.h
targets += pm-asm-offsets.s
+
+obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
new file mode 100644
index 000000000000..f1a6ece8108e
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * OMAP IOMMU quirks for various TI SoCs
+ *
+ * Copyright (C) 2015-2019 Texas Instruments Incorporated - http://www.ti.com/
+ * Suman Anna <s-anna@ti.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "powerdomain.h"
+
+int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
+ u8 *pwrst)
+{
+ struct powerdomain *pwrdm;
+ struct omap_device *od;
+ u8 next_pwrst;
+
+ od = to_omap_device(pdev);
+ if (!od)
+ return -ENODEV;
+
+ if (od->hwmods_cnt != 1)
+ return -EINVAL;
+
+ pwrdm = omap_hwmod_get_pwrdm(od->hwmods[0]);
+ if (!pwrdm)
+ return -EINVAL;
+
+ if (request)
+ *pwrst = pwrdm_read_next_pwrst(pwrdm);
+
+ if (*pwrst > PWRDM_POWER_RET)
+ return 0;
+
+ next_pwrst = request ? PWRDM_POWER_ON : *pwrst;
+
+ return pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+}
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index dfb961d8c21b..84b99d5841ae 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -190,6 +190,14 @@ static int iommu_enable(struct omap_iommu *obj)
struct platform_device *pdev = to_platform_device(obj->dev);
struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ if (pdata && pdata->set_pwrdm_constraint) {
+ err = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst);
+ if (err) {
+ dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n",
+ err);
+ }
+ }
+
if (pdata && pdata->deassert_reset) {
err = pdata->deassert_reset(pdev, pdata->reset_name);
if (err) {
@@ -209,6 +217,7 @@ static void iommu_disable(struct omap_iommu *obj)
{
struct platform_device *pdev = to_platform_device(obj->dev);
struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ int ret;
omap2_iommu_disable(obj);
@@ -216,6 +225,14 @@ static void iommu_disable(struct omap_iommu *obj)
if (pdata && pdata->assert_reset)
pdata->assert_reset(pdev, pdata->reset_name);
+
+ if (pdata && pdata->set_pwrdm_constraint) {
+ ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst);
+ if (ret) {
+ dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n",
+ ret);
+ }
+ }
}
/*
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 09968a02d291..aac1ca65ef9d 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -78,6 +78,8 @@ struct omap_iommu {
struct iommu_device iommu;
struct iommu_group *group;
+
+ u8 pwrst;
};
/**
diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h
index 44d913a7580c..1ed60265a20e 100644
--- a/include/linux/platform_data/iommu-omap.h
+++ b/include/linux/platform_data/iommu-omap.h
@@ -13,4 +13,6 @@ struct iommu_platform_data {
const char *reset_name;
int (*assert_reset)(struct platform_device *pdev, const char *name);
int (*deassert_reset)(struct platform_device *pdev, const char *name);
+ int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request,
+ u8 *pwrst);
};