summaryrefslogtreecommitdiff
path: root/drivers/gpu/sprd_iommu/v2
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/gpu/sprd_iommu/v2
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/gpu/sprd_iommu/v2')
-rw-r--r--drivers/gpu/sprd_iommu/v2/Makefile6
-rw-r--r--drivers/gpu/sprd_iommu/v2/sprd_iommu_dcam.c192
-rw-r--r--drivers/gpu/sprd_iommu/v2/sprd_iommu_dispc.c229
-rw-r--r--drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp0.c229
-rw-r--r--drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp1.c229
-rw-r--r--drivers/gpu/sprd_iommu/v2/sprd_iommu_vpp.c192
-rw-r--r--drivers/gpu/sprd_iommu/v2/sprd_iommu_vsp.c192
7 files changed, 1269 insertions, 0 deletions
diff --git a/drivers/gpu/sprd_iommu/v2/Makefile b/drivers/gpu/sprd_iommu/v2/Makefile
new file mode 100644
index 00000000..ea4985d6
--- /dev/null
+++ b/drivers/gpu/sprd_iommu/v2/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_SPRD_IOMMU) += sprd_iommu_vsp.o
+obj-$(CONFIG_SPRD_IOMMU) += sprd_iommu_dcam.o
+obj-$(CONFIG_SPRD_IOMMU) += sprd_iommu_dispc.o
+obj-$(CONFIG_SPRD_IOMMU) += sprd_iommu_gsp0.o
+obj-$(CONFIG_SPRD_IOMMU) += sprd_iommu_gsp1.o
+obj-$(CONFIG_SPRD_IOMMU) += sprd_iommu_vpp.o
diff --git a/drivers/gpu/sprd_iommu/v2/sprd_iommu_dcam.c b/drivers/gpu/sprd_iommu/v2/sprd_iommu_dcam.c
new file mode 100644
index 00000000..273c930f
--- /dev/null
+++ b/drivers/gpu/sprd_iommu/v2/sprd_iommu_dcam.c
@@ -0,0 +1,192 @@
+/*
+ * drivers/gpu/iommu/iommu.c *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include"../sprd_iommu_common.h"
+
+void sprd_iommu_dcam_clk_enable(struct sprd_iommu_dev *dev)
+{
+ pr_info("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_prepare_enable(dev->mmu_mclock);
+ clk_prepare_enable(dev->mmu_clock);
+#endif
+}
+
+void sprd_iommu_dcam_clk_disable(struct sprd_iommu_dev *dev)
+{
+ pr_info("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_disable_unprepare(dev->mmu_clock);
+ clk_disable_unprepare(dev->mmu_mclock);
+#endif
+}
+
+void sprd_iommu_dcam_open(struct sprd_iommu_dev *dev)
+{
+}
+
+void sprd_iommu_dcam_release(struct sprd_iommu_dev *dev)
+{
+}
+
+int sprd_iommu_dcam_init(struct sprd_iommu_dev *dev,
+ struct sprd_iommu_init_data *data)
+{
+ int err = -1;
+#ifndef CONFIG_SC_FPGA
+ struct device_node *np;
+
+ np = dev->misc_dev.this_device->of_node;
+ if (!np)
+ return -1;
+
+ dev->mmu_clock = of_clk_get(np, 0);
+ dev->mmu_mclock = of_clk_get(np, 1);
+
+ if (IS_ERR(dev->mmu_clock) || IS_ERR(dev->mmu_mclock)) {
+ pr_info("%s, can't get clock:%p, %p\n", __func__,
+ dev->mmu_clock, dev->mmu_mclock);
+ goto errorout;
+ }
+#endif
+ sprd_iommu_dcam_clk_enable(dev);
+ err = sprd_iommu_init(dev, data);
+ sprd_iommu_dcam_clk_disable(dev);
+
+ return err;
+
+#ifndef CONFIG_SC_FPGA
+errorout:
+ if (dev->mmu_clock)
+ clk_put(dev->mmu_clock);
+
+ if (dev->mmu_mclock)
+ clk_put(dev->mmu_mclock);
+
+ return -1;
+#endif
+}
+
+int sprd_iommu_dcam_exit(struct sprd_iommu_dev *dev)
+{
+ int err = -1;
+
+ sprd_iommu_dcam_clk_enable(dev);
+ err = sprd_iommu_exit(dev);
+ sprd_iommu_dcam_clk_disable(dev);
+
+ return err;
+}
+
+unsigned long sprd_iommu_dcam_iova_alloc(struct sprd_iommu_dev *dev,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_alloc(dev, iova_length);
+}
+
+void sprd_iommu_dcam_iova_free(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_free(dev, iova, iova_length);
+}
+
+int sprd_iommu_dcam_iova_map(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length, struct sg_table *table)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ if (0 == dev->map_count) {
+ sprd_iommu_dcam_clk_enable(dev);
+ sprd_iommu_reset_enable(dev);
+ }
+ dev->map_count++;
+ err = sprd_iommu_iova_map(dev, iova, iova_length, table);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_dcam_iova_unmap(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ err = sprd_iommu_iova_unmap(dev, iova, iova_length);
+ dev->map_count--;
+ if (0 == dev->map_count) {
+ sprd_iommu_disable(dev);
+ sprd_iommu_dcam_clk_disable(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_dcam_backup(struct sprd_iommu_dev *dev)
+{
+ int err = 0;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+
+ if (dev->map_count > 0) {
+ err = sprd_iommu_backup(dev);
+ sprd_iommu_dcam_clk_disable(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_dcam_restore(struct sprd_iommu_dev *dev)
+{
+ int err = 0;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+
+ if (dev->map_count > 0) {
+ sprd_iommu_dcam_clk_enable(dev);
+ err = sprd_iommu_restore(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_dcam_dump(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_dump(dev, iova, iova_length);
+}
+
+struct sprd_iommu_ops iommu_dcam_ops = {
+ .init = sprd_iommu_dcam_init,
+ .exit = sprd_iommu_dcam_exit,
+ .iova_alloc = sprd_iommu_dcam_iova_alloc,
+ .iova_free = sprd_iommu_dcam_iova_free,
+ .iova_map = sprd_iommu_dcam_iova_map,
+ .iova_unmap = sprd_iommu_dcam_iova_unmap,
+ .backup = sprd_iommu_dcam_backup,
+ .restore = sprd_iommu_dcam_restore,
+ .enable = sprd_iommu_dcam_clk_enable,
+ .disable = sprd_iommu_dcam_clk_disable,
+ .dump = sprd_iommu_dcam_dump,
+ .open = sprd_iommu_dcam_open,
+ .release = sprd_iommu_dcam_release,
+};
+
diff --git a/drivers/gpu/sprd_iommu/v2/sprd_iommu_dispc.c b/drivers/gpu/sprd_iommu/v2/sprd_iommu_dispc.c
new file mode 100644
index 00000000..ac0ebd6a
--- /dev/null
+++ b/drivers/gpu/sprd_iommu/v2/sprd_iommu_dispc.c
@@ -0,0 +1,229 @@
+/*
+ * drivers/gpu/iommu/iommu.c *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include"../sprd_iommu_common.h"
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void sprd_iommu_dispc_early_suspend(struct early_suspend *es)
+{
+ int err = -1;
+
+ struct sprd_iommu_dev *dev = container_of(es,
+ struct sprd_iommu_dev, early_suspend);
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_backup(dev);
+ mutex_unlock(&dev->mutex_map);
+}
+
+static void sprd_iommu_dispc_late_resume(struct early_suspend *es)
+{
+ int err = -1;
+
+ struct sprd_iommu_dev *dev = container_of(es,
+ struct sprd_iommu_dev, early_suspend);
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_restore(dev);
+ mutex_unlock(&dev->mutex_map);
+}
+#endif
+
+void sprd_iommu_dispc_clk_enable(struct sprd_iommu_dev *dev)
+{
+ pr_debug("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_prepare_enable(dev->mmu_mclock);
+ clk_prepare_enable(dev->mmu_clock);
+#endif
+}
+
+void sprd_iommu_dispc_clk_disable(struct sprd_iommu_dev *dev)
+{
+ pr_debug("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_disable_unprepare(dev->mmu_clock);
+ clk_disable_unprepare(dev->mmu_mclock);
+#endif
+}
+
+void sprd_iommu_dispc_open(struct sprd_iommu_dev *dev)
+{
+}
+
+void sprd_iommu_dispc_release(struct sprd_iommu_dev *dev)
+{
+}
+
+int sprd_iommu_dispc_init(struct sprd_iommu_dev *dev,
+ struct sprd_iommu_init_data *data)
+{
+ int err = -1;
+#ifndef CONFIG_SC_FPGA
+ struct device_node *np;
+
+ np = dev->misc_dev.this_device->of_node;
+ if (!np)
+ return -1;
+
+ dev->mmu_mclock = of_clk_get(np, 0);
+ dev->mmu_clock = of_clk_get(np, 2);
+
+ if (IS_ERR(dev->mmu_clock) || IS_ERR(dev->mmu_mclock)) {
+ pr_info("%s, can't get clock:%p, %p\n", __func__,
+ dev->mmu_clock, dev->mmu_mclock);
+ goto errorout;
+ }
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ dev->early_suspend.suspend = sprd_iommu_dispc_early_suspend;
+ dev->early_suspend.resume = sprd_iommu_dispc_late_resume;
+ dev->early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
+ register_early_suspend(&dev->early_suspend);
+#endif
+
+ sprd_iommu_dispc_clk_enable(dev);
+ err = sprd_iommu_init(dev, data);
+ sprd_iommu_dispc_clk_disable(dev);
+
+ return err;
+
+#ifndef CONFIG_SC_FPGA
+errorout:
+ if (dev->mmu_clock)
+ clk_put(dev->mmu_clock);
+
+ if (dev->mmu_mclock)
+ clk_put(dev->mmu_mclock);
+
+ return -1;
+#endif
+}
+
+int sprd_iommu_dispc_exit(struct sprd_iommu_dev *dev)
+{
+ int err = -1;
+
+ sprd_iommu_dispc_clk_enable(dev);
+ err = sprd_iommu_exit(dev);
+ sprd_iommu_dispc_clk_disable(dev);
+
+ return err;
+}
+
+unsigned long sprd_iommu_dispc_iova_alloc(struct sprd_iommu_dev *dev,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_alloc(dev, iova_length);
+}
+
+void sprd_iommu_dispc_iova_free(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ sprd_iommu_iova_free(dev, iova, iova_length);
+}
+
+int sprd_iommu_dispc_iova_map(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length, struct sg_table *table)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ if (0 == dev->map_count)
+ sprd_iommu_enable(dev);
+ dev->map_count++;
+
+ err = sprd_iommu_iova_map(dev, iova, iova_length, table);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_dispc_iova_unmap(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ err = sprd_iommu_iova_unmap(dev, iova, iova_length);
+
+ dev->map_count--;
+ if (0 == dev->map_count)
+ sprd_iommu_disable(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_dispc_backup(struct sprd_iommu_dev *dev)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ return 0;
+#else
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_backup(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+#endif
+}
+
+int sprd_iommu_dispc_restore(struct sprd_iommu_dev *dev)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ return 0;
+#else
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_restore(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return 0;
+#endif
+}
+
+int sprd_iommu_dispc_dump(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_dump(dev, iova, iova_length);
+}
+
+struct sprd_iommu_ops iommu_dispc_ops = {
+ .init = sprd_iommu_dispc_init,
+ .exit = sprd_iommu_dispc_exit,
+ .iova_alloc = sprd_iommu_dispc_iova_alloc,
+ .iova_free = sprd_iommu_dispc_iova_free,
+ .iova_map = sprd_iommu_dispc_iova_map,
+ .iova_unmap = sprd_iommu_dispc_iova_unmap,
+ .backup = sprd_iommu_dispc_backup,
+ .restore = sprd_iommu_dispc_restore,
+ .enable = sprd_iommu_dispc_clk_enable,
+ .disable = sprd_iommu_dispc_clk_disable,
+ .dump = sprd_iommu_dispc_dump,
+ .open = sprd_iommu_dispc_open,
+ .release = sprd_iommu_dispc_release,
+};
+
diff --git a/drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp0.c b/drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp0.c
new file mode 100644
index 00000000..27a37502
--- /dev/null
+++ b/drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp0.c
@@ -0,0 +1,229 @@
+/*
+ * drivers/gpu/iommu/iommu.c *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include"../sprd_iommu_common.h"
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void sprd_iommu_gsp0_early_suspend(struct early_suspend *es)
+{
+ int err = -1;
+
+ struct sprd_iommu_dev *dev = container_of(es,
+ struct sprd_iommu_dev, early_suspend);
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_backup(dev);
+ mutex_unlock(&dev->mutex_map);
+}
+
+static void sprd_iommu_gsp0_late_resume(struct early_suspend *es)
+{
+ int err = -1;
+
+ struct sprd_iommu_dev *dev = container_of(es,
+ struct sprd_iommu_dev, early_suspend);
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_restore(dev);
+ mutex_unlock(&dev->mutex_map);
+}
+#endif
+
+void sprd_iommu_gsp0_clk_enable(struct sprd_iommu_dev *dev)
+{
+ pr_debug("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_prepare_enable(dev->mmu_mclock);
+ clk_prepare_enable(dev->mmu_clock);
+#endif
+}
+
+void sprd_iommu_gsp0_clk_disable(struct sprd_iommu_dev *dev)
+{
+ pr_debug("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_disable_unprepare(dev->mmu_clock);
+ clk_disable_unprepare(dev->mmu_mclock);
+#endif
+}
+
+void sprd_iommu_gsp0_open(struct sprd_iommu_dev *dev)
+{
+}
+
+void sprd_iommu_gsp0_release(struct sprd_iommu_dev *dev)
+{
+}
+
+int sprd_iommu_gsp0_init(struct sprd_iommu_dev *dev,
+ struct sprd_iommu_init_data *data)
+{
+ int err = -1;
+#ifndef CONFIG_SC_FPGA
+ struct device_node *np;
+
+ np = dev->misc_dev.this_device->of_node;
+ if (!np)
+ return -1;
+
+ dev->mmu_mclock = of_clk_get(np, 0);
+ dev->mmu_clock = of_clk_get(np, 2);
+
+ if (IS_ERR(dev->mmu_clock) || IS_ERR(dev->mmu_mclock)) {
+ pr_info("%s, can't get clock:%p, %p\n", __func__,
+ dev->mmu_clock, dev->mmu_mclock);
+ goto errorout;
+ }
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ dev->early_suspend.suspend = sprd_iommu_gsp0_early_suspend;
+ dev->early_suspend.resume = sprd_iommu_gsp0_late_resume;
+ dev->early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
+ register_early_suspend(&dev->early_suspend);
+#endif
+
+ sprd_iommu_gsp0_clk_enable(dev);
+ err = sprd_iommu_init(dev, data);
+ sprd_iommu_gsp0_clk_disable(dev);
+
+ return err;
+
+#ifndef CONFIG_SC_FPGA
+errorout:
+ if (dev->mmu_clock)
+ clk_put(dev->mmu_clock);
+
+ if (dev->mmu_mclock)
+ clk_put(dev->mmu_mclock);
+
+ return -1;
+#endif
+}
+
+int sprd_iommu_gsp0_exit(struct sprd_iommu_dev *dev)
+{
+ int err = -1;
+
+ sprd_iommu_gsp0_clk_enable(dev);
+ err = sprd_iommu_exit(dev);
+ sprd_iommu_gsp0_clk_disable(dev);
+
+ return err;
+}
+
+unsigned long sprd_iommu_gsp0_iova_alloc(struct sprd_iommu_dev *dev,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_alloc(dev, iova_length);
+}
+
+void sprd_iommu_gsp0_iova_free(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ sprd_iommu_iova_free(dev, iova, iova_length);
+}
+
+int sprd_iommu_gsp0_iova_map(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length, struct sg_table *table)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ if (0 == dev->map_count)
+ sprd_iommu_enable(dev);
+ dev->map_count++;
+
+ err = sprd_iommu_iova_map(dev, iova, iova_length, table);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_gsp0_iova_unmap(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ err = sprd_iommu_iova_unmap(dev, iova, iova_length);
+
+ dev->map_count--;
+ if (0 == dev->map_count)
+ sprd_iommu_disable(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_gsp0_backup(struct sprd_iommu_dev *dev)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ return 0;
+#else
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_backup(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+#endif
+}
+
+int sprd_iommu_gsp0_restore(struct sprd_iommu_dev *dev)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ return 0;
+#else
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_restore(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return 0;
+#endif
+}
+
+int sprd_iommu_gsp0_dump(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_dump(dev, iova, iova_length);
+}
+
+struct sprd_iommu_ops iommu_gsp0_ops = {
+ .init = sprd_iommu_gsp0_init,
+ .exit = sprd_iommu_gsp0_exit,
+ .iova_alloc = sprd_iommu_gsp0_iova_alloc,
+ .iova_free = sprd_iommu_gsp0_iova_free,
+ .iova_map = sprd_iommu_gsp0_iova_map,
+ .iova_unmap = sprd_iommu_gsp0_iova_unmap,
+ .backup = sprd_iommu_gsp0_backup,
+ .restore = sprd_iommu_gsp0_restore,
+ .enable = sprd_iommu_gsp0_clk_enable,
+ .disable = sprd_iommu_gsp0_clk_disable,
+ .dump = sprd_iommu_gsp0_dump,
+ .open = sprd_iommu_gsp0_open,
+ .release = sprd_iommu_gsp0_release,
+};
+
diff --git a/drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp1.c b/drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp1.c
new file mode 100644
index 00000000..3e3fb359
--- /dev/null
+++ b/drivers/gpu/sprd_iommu/v2/sprd_iommu_gsp1.c
@@ -0,0 +1,229 @@
+/*
+ * drivers/gpu/iommu/iommu.c *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include"../sprd_iommu_common.h"
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void sprd_iommu_gsp1_early_suspend(struct early_suspend *es)
+{
+ int err = -1;
+
+ struct sprd_iommu_dev *dev = container_of(es,
+ struct sprd_iommu_dev, early_suspend);
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_backup(dev);
+ mutex_unlock(&dev->mutex_map);
+}
+
+static void sprd_iommu_gsp1_late_resume(struct early_suspend *es)
+{
+ int err = -1;
+
+ struct sprd_iommu_dev *dev = container_of(es,
+ struct sprd_iommu_dev, early_suspend);
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_restore(dev);
+ mutex_unlock(&dev->mutex_map);
+}
+#endif
+
+void sprd_iommu_gsp1_clk_enable(struct sprd_iommu_dev *dev)
+{
+ pr_debug("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_prepare_enable(dev->mmu_mclock);
+ clk_prepare_enable(dev->mmu_clock);
+#endif
+}
+
+void sprd_iommu_gsp1_clk_disable(struct sprd_iommu_dev *dev)
+{
+ pr_debug("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_disable_unprepare(dev->mmu_clock);
+ clk_disable_unprepare(dev->mmu_mclock);
+#endif
+}
+
+void sprd_iommu_gsp1_open(struct sprd_iommu_dev *dev)
+{
+}
+
+void sprd_iommu_gsp1_release(struct sprd_iommu_dev *dev)
+{
+}
+
+int sprd_iommu_gsp1_init(struct sprd_iommu_dev *dev,
+ struct sprd_iommu_init_data *data)
+{
+ int err = -1;
+#ifndef CONFIG_SC_FPGA
+ struct device_node *np;
+
+ np = dev->misc_dev.this_device->of_node;
+ if (!np)
+ return -1;
+
+ dev->mmu_mclock = of_clk_get(np, 0);
+ dev->mmu_clock = of_clk_get(np, 2);
+
+ if (IS_ERR(dev->mmu_clock) || IS_ERR(dev->mmu_mclock)) {
+ pr_info("%s, can't get clock:%p, %p\n", __func__,
+ dev->mmu_clock, dev->mmu_mclock);
+ goto errorout;
+ }
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ dev->early_suspend.suspend = sprd_iommu_gsp1_early_suspend;
+ dev->early_suspend.resume = sprd_iommu_gsp1_late_resume;
+ dev->early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
+ register_early_suspend(&dev->early_suspend);
+#endif
+
+ sprd_iommu_gsp1_clk_enable(dev);
+ err = sprd_iommu_init(dev, data);
+ sprd_iommu_gsp1_clk_disable(dev);
+
+ return err;
+
+#ifndef CONFIG_SC_FPGA
+errorout:
+ if (dev->mmu_clock)
+ clk_put(dev->mmu_clock);
+
+ if (dev->mmu_mclock)
+ clk_put(dev->mmu_mclock);
+
+ return -1;
+#endif
+}
+
+int sprd_iommu_gsp1_exit(struct sprd_iommu_dev *dev)
+{
+ int err = -1;
+
+ sprd_iommu_gsp1_clk_enable(dev);
+ err = sprd_iommu_exit(dev);
+ sprd_iommu_gsp1_clk_disable(dev);
+
+ return err;
+}
+
+unsigned long sprd_iommu_gsp1_iova_alloc(struct sprd_iommu_dev *dev,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_alloc(dev, iova_length);
+}
+
+void sprd_iommu_gsp1_iova_free(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ sprd_iommu_iova_free(dev, iova, iova_length);
+}
+
+int sprd_iommu_gsp1_iova_map(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length, struct sg_table *table)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ if (0 == dev->map_count)
+ sprd_iommu_enable(dev);
+ dev->map_count++;
+
+ err = sprd_iommu_iova_map(dev, iova, iova_length, table);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_gsp1_iova_unmap(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ err = sprd_iommu_iova_unmap(dev, iova, iova_length);
+
+ dev->map_count--;
+ if (0 == dev->map_count)
+ sprd_iommu_disable(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_gsp1_backup(struct sprd_iommu_dev *dev)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ return 0;
+#else
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_backup(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+#endif
+}
+
+int sprd_iommu_gsp1_restore(struct sprd_iommu_dev *dev)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ return 0;
+#else
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+ if (dev->map_count > 0)
+ err = sprd_iommu_restore(dev);
+ mutex_unlock(&dev->mutex_map);
+
+ return 0;
+#endif
+}
+
+int sprd_iommu_gsp1_dump(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_dump(dev, iova, iova_length);
+}
+
+struct sprd_iommu_ops iommu_gsp1_ops = {
+ .init = sprd_iommu_gsp1_init,
+ .exit = sprd_iommu_gsp1_exit,
+ .iova_alloc = sprd_iommu_gsp1_iova_alloc,
+ .iova_free = sprd_iommu_gsp1_iova_free,
+ .iova_map = sprd_iommu_gsp1_iova_map,
+ .iova_unmap = sprd_iommu_gsp1_iova_unmap,
+ .backup = sprd_iommu_gsp1_backup,
+ .restore = sprd_iommu_gsp1_restore,
+ .enable = sprd_iommu_gsp1_clk_enable,
+ .disable = sprd_iommu_gsp1_clk_disable,
+ .dump = sprd_iommu_gsp1_dump,
+ .open = sprd_iommu_gsp1_open,
+ .release = sprd_iommu_gsp1_release,
+};
+
diff --git a/drivers/gpu/sprd_iommu/v2/sprd_iommu_vpp.c b/drivers/gpu/sprd_iommu/v2/sprd_iommu_vpp.c
new file mode 100644
index 00000000..ba377e2f
--- /dev/null
+++ b/drivers/gpu/sprd_iommu/v2/sprd_iommu_vpp.c
@@ -0,0 +1,192 @@
+/*
+ * drivers/gpu/iommu/iommu.c *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include"../sprd_iommu_common.h"
+
+void sprd_iommu_vpp_clk_enable(struct sprd_iommu_dev *dev)
+{
+ pr_info("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_prepare_enable(dev->mmu_mclock);
+ clk_prepare_enable(dev->mmu_clock);
+#endif
+}
+
+void sprd_iommu_vpp_clk_disable(struct sprd_iommu_dev *dev)
+{
+ pr_info("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_disable_unprepare(dev->mmu_clock);
+ clk_disable_unprepare(dev->mmu_mclock);
+#endif
+}
+
+void sprd_iommu_vpp_open(struct sprd_iommu_dev *dev)
+{
+}
+
+void sprd_iommu_vpp_release(struct sprd_iommu_dev *dev)
+{
+}
+
+int sprd_iommu_vpp_init(struct sprd_iommu_dev *dev,
+ struct sprd_iommu_init_data *data)
+{
+ int err = -1;
+#ifndef CONFIG_SC_FPGA
+ struct device_node *np;
+
+ np = dev->misc_dev.this_device->of_node;
+ if (!np)
+ return -1;
+
+ dev->mmu_clock = of_clk_get(np, 0);
+ dev->mmu_mclock = of_clk_get(np, 1);
+
+ if (IS_ERR(dev->mmu_clock) || IS_ERR(dev->mmu_mclock)) {
+ pr_info("%s, can't get clock:%p, %p\n", __func__,
+ dev->mmu_clock, dev->mmu_mclock);
+ goto errorout;
+ }
+#endif
+ sprd_iommu_vpp_clk_enable(dev);
+ err = sprd_iommu_init(dev, data);
+ sprd_iommu_vpp_clk_disable(dev);
+
+ return err;
+
+#ifndef CONFIG_SC_FPGA
+errorout:
+ if (dev->mmu_clock)
+ clk_put(dev->mmu_clock);
+
+ if (dev->mmu_mclock)
+ clk_put(dev->mmu_mclock);
+
+ return -1;
+#endif
+}
+
+int sprd_iommu_vpp_exit(struct sprd_iommu_dev *dev)
+{
+ int err = -1;
+
+ sprd_iommu_vpp_clk_enable(dev);
+ err = sprd_iommu_exit(dev);
+ sprd_iommu_vpp_clk_disable(dev);
+
+ return err;
+}
+
+unsigned long sprd_iommu_vpp_iova_alloc(struct sprd_iommu_dev *dev,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_alloc(dev, iova_length);
+}
+
+void sprd_iommu_vpp_iova_free(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_free(dev, iova, iova_length);
+}
+
+int sprd_iommu_vpp_iova_map(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length, struct sg_table *table)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ if (0 == dev->map_count) {
+ sprd_iommu_vpp_clk_enable(dev);
+ sprd_iommu_reset_enable(dev);
+ }
+ dev->map_count++;
+ err = sprd_iommu_iova_map(dev, iova, iova_length, table);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vpp_iova_unmap(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ err = sprd_iommu_iova_unmap(dev, iova, iova_length);
+ dev->map_count--;
+ if (0 == dev->map_count) {
+ sprd_iommu_disable(dev);
+ sprd_iommu_vpp_clk_disable(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vpp_backup(struct sprd_iommu_dev *dev)
+{
+ int err = 0;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+
+ if (dev->map_count > 0) {
+ err = sprd_iommu_backup(dev);
+ sprd_iommu_vpp_clk_disable(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vpp_restore(struct sprd_iommu_dev *dev)
+{
+ int err = 0;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+
+ if (dev->map_count > 0) {
+ sprd_iommu_vpp_clk_enable(dev);
+ err = sprd_iommu_restore(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vpp_dump(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_dump(dev, iova, iova_length);
+}
+
+struct sprd_iommu_ops iommu_vpp_ops = {
+ .init = sprd_iommu_vpp_init,
+ .exit = sprd_iommu_vpp_exit,
+ .iova_alloc = sprd_iommu_vpp_iova_alloc,
+ .iova_free = sprd_iommu_vpp_iova_free,
+ .iova_map = sprd_iommu_vpp_iova_map,
+ .iova_unmap = sprd_iommu_vpp_iova_unmap,
+ .backup = sprd_iommu_vpp_backup,
+ .restore = sprd_iommu_vpp_restore,
+ .enable = sprd_iommu_vpp_clk_enable,
+ .disable = sprd_iommu_vpp_clk_disable,
+ .dump = sprd_iommu_vpp_dump,
+ .open = sprd_iommu_vpp_open,
+ .release = sprd_iommu_vpp_release,
+};
+
diff --git a/drivers/gpu/sprd_iommu/v2/sprd_iommu_vsp.c b/drivers/gpu/sprd_iommu/v2/sprd_iommu_vsp.c
new file mode 100644
index 00000000..2f1a28b9
--- /dev/null
+++ b/drivers/gpu/sprd_iommu/v2/sprd_iommu_vsp.c
@@ -0,0 +1,192 @@
+/*
+ * drivers/gpu/iommu/iommu.c *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include"../sprd_iommu_common.h"
+
+void sprd_iommu_vsp_clk_enable(struct sprd_iommu_dev *dev)
+{
+ pr_info("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_prepare_enable(dev->mmu_mclock);
+ clk_prepare_enable(dev->mmu_clock);
+#endif
+}
+
+void sprd_iommu_vsp_clk_disable(struct sprd_iommu_dev *dev)
+{
+ pr_info("%s\n", __func__);
+#ifndef CONFIG_SC_FPGA
+ clk_disable_unprepare(dev->mmu_clock);
+ clk_disable_unprepare(dev->mmu_mclock);
+#endif
+}
+
+void sprd_iommu_vsp_open(struct sprd_iommu_dev *dev)
+{
+}
+
+void sprd_iommu_vsp_release(struct sprd_iommu_dev *dev)
+{
+}
+
+int sprd_iommu_vsp_init(struct sprd_iommu_dev *dev,
+ struct sprd_iommu_init_data *data)
+{
+ int err = -1;
+#ifndef CONFIG_SC_FPGA
+ struct device_node *np;
+
+ np = dev->misc_dev.this_device->of_node;
+ if (!np)
+ return -1;
+
+ dev->mmu_clock = of_clk_get(np, 0);
+ dev->mmu_mclock = of_clk_get(np, 1);
+
+ if (IS_ERR(dev->mmu_clock) || IS_ERR(dev->mmu_mclock)) {
+ pr_info("%s, can't get clock:%p, %p\n", __func__,
+ dev->mmu_clock, dev->mmu_mclock);
+ goto errorout;
+ }
+#endif
+ sprd_iommu_vsp_clk_enable(dev);
+ err = sprd_iommu_init(dev, data);
+ sprd_iommu_vsp_clk_disable(dev);
+
+ return err;
+
+#ifndef CONFIG_SC_FPGA
+errorout:
+ if (dev->mmu_clock)
+ clk_put(dev->mmu_clock);
+
+ if (dev->mmu_mclock)
+ clk_put(dev->mmu_mclock);
+
+ return -1;
+#endif
+}
+
+int sprd_iommu_vsp_exit(struct sprd_iommu_dev *dev)
+{
+ int err = -1;
+
+ sprd_iommu_vsp_clk_enable(dev);
+ err = sprd_iommu_exit(dev);
+ sprd_iommu_vsp_clk_disable(dev);
+
+ return err;
+}
+
+unsigned long sprd_iommu_vsp_iova_alloc(struct sprd_iommu_dev *dev,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_alloc(dev, iova_length);
+}
+
+void sprd_iommu_vsp_iova_free(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_iova_free(dev, iova, iova_length);
+}
+
+int sprd_iommu_vsp_iova_map(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length, struct sg_table *table)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ if (0 == dev->map_count) {
+ sprd_iommu_vsp_clk_enable(dev);
+ sprd_iommu_reset_enable(dev);
+ }
+ dev->map_count++;
+ err = sprd_iommu_iova_map(dev, iova, iova_length, table);
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vsp_iova_unmap(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ int err = -1;
+
+ mutex_lock(&dev->mutex_map);
+ err = sprd_iommu_iova_unmap(dev, iova, iova_length);
+ dev->map_count--;
+ if (0 == dev->map_count) {
+ sprd_iommu_disable(dev);
+ sprd_iommu_vsp_clk_disable(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vsp_backup(struct sprd_iommu_dev *dev)
+{
+ int err = 0;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+
+ if (dev->map_count > 0) {
+ err = sprd_iommu_backup(dev);
+ sprd_iommu_vsp_clk_disable(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vsp_restore(struct sprd_iommu_dev *dev)
+{
+ int err = 0;
+
+ mutex_lock(&dev->mutex_map);
+ pr_info("%s, map_count:%d\n", __func__, dev->map_count);
+
+ if (dev->map_count > 0) {
+ sprd_iommu_vsp_clk_enable(dev);
+ err = sprd_iommu_restore(dev);
+ }
+ mutex_unlock(&dev->mutex_map);
+
+ return err;
+}
+
+int sprd_iommu_vsp_dump(struct sprd_iommu_dev *dev, unsigned long iova,
+ size_t iova_length)
+{
+ return sprd_iommu_dump(dev, iova, iova_length);
+}
+
+struct sprd_iommu_ops iommu_vsp_ops = {
+ .init = sprd_iommu_vsp_init,
+ .exit = sprd_iommu_vsp_exit,
+ .iova_alloc = sprd_iommu_vsp_iova_alloc,
+ .iova_free = sprd_iommu_vsp_iova_free,
+ .iova_map = sprd_iommu_vsp_iova_map,
+ .iova_unmap = sprd_iommu_vsp_iova_unmap,
+ .backup = sprd_iommu_vsp_backup,
+ .restore = sprd_iommu_vsp_restore,
+ .enable = sprd_iommu_vsp_clk_enable,
+ .disable = sprd_iommu_vsp_clk_disable,
+ .dump = sprd_iommu_vsp_dump,
+ .open = sprd_iommu_vsp_open,
+ .release = sprd_iommu_vsp_release,
+};
+