blob: ebecd114e3cbc1959229a37ffad324b627da18a0 [file] [log] [blame]
Olav Haugan0858ae02013-06-04 16:51:50 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14#include <linux/errno.h>
15#include <linux/err.h>
16#include <linux/list.h>
17#include <linux/mutex.h>
18#include <linux/platform_device.h>
19#include <linux/export.h>
20#include <linux/iommu.h>
21#include <mach/iommu.h>
22
23static DEFINE_MUTEX(iommu_list_lock);
24static LIST_HEAD(iommu_list);
25
26static struct iommu_access_ops *iommu_access_ops;
27
28struct bus_type msm_iommu_sec_bus_type = {
29 .name = "msm_iommu_sec_bus",
30};
31
32void msm_set_iommu_access_ops(struct iommu_access_ops *ops)
33{
34 iommu_access_ops = ops;
35}
36
37struct iommu_access_ops *msm_get_iommu_access_ops()
38{
39 BUG_ON(iommu_access_ops == NULL);
40 return iommu_access_ops;
41}
42EXPORT_SYMBOL(msm_get_iommu_access_ops);
43
44void msm_iommu_add_drv(struct msm_iommu_drvdata *drv)
45{
46 mutex_lock(&iommu_list_lock);
47 list_add(&drv->list, &iommu_list);
48 mutex_unlock(&iommu_list_lock);
49}
50
51void msm_iommu_remove_drv(struct msm_iommu_drvdata *drv)
52{
53 mutex_lock(&iommu_list_lock);
54 list_del(&drv->list);
55 mutex_unlock(&iommu_list_lock);
56}
57
58static int find_iommu_ctx(struct device *dev, void *data)
59{
60 struct msm_iommu_ctx_drvdata *c;
61
62 c = dev_get_drvdata(dev);
63 if (!c || !c->name)
64 return 0;
65
66 return !strcmp(data, c->name);
67}
68
69static struct device *find_context(struct device *dev, const char *name)
70{
71 return device_find_child(dev, (void *)name, find_iommu_ctx);
72}
73
74struct device *msm_iommu_get_ctx(const char *ctx_name)
75{
76 struct msm_iommu_drvdata *drv;
77 struct device *dev = NULL;
78
79 mutex_lock(&iommu_list_lock);
80 list_for_each_entry(drv, &iommu_list, list) {
81 dev = find_context(drv->dev, ctx_name);
82 if (dev)
83 break;
84 }
85 mutex_unlock(&iommu_list_lock);
86
87 put_device(dev);
88
89 if (!dev || !dev_get_drvdata(dev)) {
90 pr_debug("Could not find context <%s>\n", ctx_name);
91 dev = ERR_PTR(-EPROBE_DEFER);
92 }
93
94 return dev;
95}
96EXPORT_SYMBOL(msm_iommu_get_ctx);
97