[COMMON] iommu/exynos: add skeleton exynos iommu driver
authorJanghyuck Kim <janghyuck.kim@samsung.com>
Tue, 19 Apr 2016 05:28:16 +0000 (14:28 +0900)
committerSangwook Ju <sw.ju@samsung.com>
Mon, 14 May 2018 10:45:17 +0000 (19:45 +0900)
Basic structures for domain, master and sysmmu are defined.
Skeleton functions of iommu_ops are added.

Change-Id: I501f6a82357a1e37e3d14bbb0f2c7ad4c516090f
Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
drivers/iommu/exynos-iommu.c [new file with mode: 0644]
drivers/iommu/exynos-iommu.h [new file with mode: 0644]

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
new file mode 100644 (file)
index 0000000..1d5e930
--- /dev/null
@@ -0,0 +1,125 @@
+/* linux/drivers/iommu/exynos_iommu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_iommu.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+
+#include "exynos-iommu.h"
+
+static int __init exynos_sysmmu_probe(struct platform_device *pdev)
+{
+       /* Dummy */
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_sysmmu_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int exynos_sysmmu_resume(struct device *dev)
+{
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops sysmmu_pm_ops = {
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_sysmmu_suspend, exynos_sysmmu_resume)
+};
+
+static const struct of_device_id sysmmu_of_match[] __initconst = {
+       { .compatible   = "samsung,exynos-sysmmu", },
+       { },
+};
+
+static struct platform_driver exynos_sysmmu_driver __refdata = {
+       .probe  = exynos_sysmmu_probe,
+       .driver = {
+               .name           = "exynos-sysmmu",
+               .of_match_table = sysmmu_of_match,
+               .pm             = &sysmmu_pm_ops,
+       }
+};
+
+static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)
+{
+       return NULL;
+}
+
+static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)
+{
+}
+
+static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
+                                  struct device *master)
+{
+       return 0;
+}
+
+static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
+                                   struct device *master)
+{
+}
+
+static int exynos_iommu_map(struct iommu_domain *iommu_domain,
+                           unsigned long l_iova, phys_addr_t paddr, size_t size,
+                           int prot)
+{
+       return 0;
+}
+
+static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain,
+                                unsigned long l_iova, size_t size)
+{
+       return 0;
+}
+
+static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
+                                         dma_addr_t d_iova)
+{
+       return 0;
+}
+
+static int exynos_iommu_of_xlate(struct device *master,
+                                struct of_phandle_args *spec)
+{
+       return 0;
+}
+
+static struct iommu_ops exynos_iommu_ops = {
+       .domain_alloc = exynos_iommu_domain_alloc,
+       .domain_free = exynos_iommu_domain_free,
+       .attach_dev = exynos_iommu_attach_device,
+       .detach_dev = exynos_iommu_detach_device,
+       .map = exynos_iommu_map,
+       .unmap = exynos_iommu_unmap,
+       .map_sg = default_iommu_map_sg,
+       .iova_to_phys = exynos_iommu_iova_to_phys,
+       .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
+       .of_xlate = exynos_iommu_of_xlate,
+};
+
+IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL);
diff --git a/drivers/iommu/exynos-iommu.h b/drivers/iommu/exynos-iommu.h
new file mode 100644 (file)
index 0000000..8f6d312
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Data structure definition for Exynos IOMMU driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _EXYNOS_IOMMU_H_
+#define _EXYNOS_IOMMU_H_
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/genalloc.h>
+#include <linux/iommu.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+
+typedef u32 sysmmu_pte_t;
+
+#define SECT_ORDER 20
+#define LPAGE_ORDER 16
+#define SPAGE_ORDER 12
+
+#define SECT_SIZE (1 << SECT_ORDER)
+#define LPAGE_SIZE (1 << LPAGE_ORDER)
+#define SPAGE_SIZE (1 << SPAGE_ORDER)
+
+#define SECT_MASK (~(SECT_SIZE - 1))
+#define LPAGE_MASK (~(LPAGE_SIZE - 1))
+#define SPAGE_MASK (~(SPAGE_SIZE - 1))
+
+#define NUM_LV2ENTRIES (SECT_SIZE / SPAGE_SIZE)
+#define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t))
+
+/*
+ * This structure exynos specific generalization of struct iommu_domain.
+ * It contains list of all master devices represented by owner, which has
+ * been attached to this domain and page tables of IO address space defined by
+ * it. It is usually referenced by 'domain' pointer.
+ */
+struct exynos_iommu_domain {
+       struct iommu_domain domain;     /* generic domain data structure */
+       sysmmu_pte_t *pgtable;          /* lv1 page table, 16KB */
+       spinlock_t pgtablelock;         /* lock for modifying page table */
+       struct list_head clients_list;  /* list of exynos_iommu_owner.client */
+       atomic_t *lv2entcnt;    /* free lv2 entry counter for each section */
+       spinlock_t lock;                /* lock for modifying clients_list */
+};
+
+/*
+ * This structure is attached to dev.archdata.iommu of the master device
+ * on device add, contains a list of SYSMMU controllers defined by device tree,
+ * which are bound to given master device. It is usually referenced by 'owner'
+ * pointer.
+*/
+struct exynos_iommu_owner {
+       struct exynos_iommu_owner *next;
+       struct list_head sysmmu_list;   /* list of sysmmu_drvdata */
+       spinlock_t lock;                /* lock for modifying sysmmu_list */
+       struct iommu_domain *domain;    /* domain of owner */
+       struct device *master;          /* master device */
+       struct list_head client;        /* node for owner clients_list */
+};
+
+/*
+ * This structure hold all data of a single SYSMMU controller, this includes
+ * hw resources like registers and clocks, pointers and list nodes to connect
+ * it to all other structures, internal state and parameters read from device
+ * tree. It is usually referenced by 'data' pointer.
+ */
+struct sysmmu_drvdata {
+       struct sysmmu_drvdata *next;
+       struct device *sysmmu;          /* SYSMMU controller device */
+       void __iomem *sfrbase;          /* our registers */
+       struct clk *clk;                /* SYSMMU's clock */
+       int activations;                /* number of calls to sysmmu_enable */
+       int runtime_active;     /* Runtime PM activated count from master */
+       spinlock_t lock;                /* lock for modyfying state */
+       phys_addr_t pgtable;            /* assigned page table structure */
+       unsigned int version;           /* our version */
+};
+#endif /* _EXYNOS_IOMMU_H_ */