From c8a2ce8396b92d9a598d875bd015b787de89db91 Mon Sep 17 00:00:00 2001 From: Janghyuck Kim Date: Tue, 19 Apr 2016 14:28:16 +0900 Subject: [PATCH] [COMMON] iommu/exynos: add skeleton exynos iommu driver Basic structures for domain, master and sysmmu are defined. Skeleton functions of iommu_ops are added. Change-Id: I501f6a82357a1e37e3d14bbb0f2c7ad4c516090f Signed-off-by: Janghyuck Kim --- drivers/iommu/exynos-iommu.c | 125 +++++++++++++++++++++++++++++++++++ drivers/iommu/exynos-iommu.h | 88 ++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 drivers/iommu/exynos-iommu.c create mode 100644 drivers/iommu/exynos-iommu.h diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c new file mode 100644 index 000000000000..1d5e93032757 --- /dev/null +++ b/drivers/iommu/exynos-iommu.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 index 000000000000..8f6d312d5816 --- /dev/null +++ b/drivers/iommu/exynos-iommu.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +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_ */ -- 2.20.1