]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/exynos/exynos_drm_iommu.c
regmap: debugfs: Fix seeking from the cache
[karo-tx-linux.git] / drivers / gpu / drm / exynos / exynos_drm_iommu.c
1 /* exynos_drm_iommu.c
2  *
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  * Author: Inki Dae <inki.dae@samsung.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 #include <drmP.h>
27 #include <drm/exynos_drm.h>
28
29 #include <linux/dma-mapping.h>
30 #include <linux/iommu.h>
31 #include <linux/kref.h>
32
33 #include <asm/dma-iommu.h>
34
35 #include "exynos_drm_drv.h"
36 #include "exynos_drm_iommu.h"
37
38 /*
39  * drm_create_iommu_mapping - create a mapping structure
40  *
41  * @drm_dev: DRM device
42  */
43 int drm_create_iommu_mapping(struct drm_device *drm_dev)
44 {
45         struct dma_iommu_mapping *mapping = NULL;
46         struct exynos_drm_private *priv = drm_dev->dev_private;
47         struct device *dev = drm_dev->dev;
48
49         if (!priv->da_start)
50                 priv->da_start = EXYNOS_DEV_ADDR_START;
51         if (!priv->da_space_size)
52                 priv->da_space_size = EXYNOS_DEV_ADDR_SIZE;
53         if (!priv->da_space_order)
54                 priv->da_space_order = EXYNOS_DEV_ADDR_ORDER;
55
56         mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start,
57                                                 priv->da_space_size,
58                                                 priv->da_space_order);
59         if (IS_ERR(mapping))
60                 return PTR_ERR(mapping);
61
62         dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
63                                         GFP_KERNEL);
64         dma_set_max_seg_size(dev, 0xffffffffu);
65         dev->archdata.mapping = mapping;
66
67         return 0;
68 }
69
70 /*
71  * drm_release_iommu_mapping - release iommu mapping structure
72  *
73  * @drm_dev: DRM device
74  *
75  * if mapping->kref becomes 0 then all things related to iommu mapping
76  * will be released
77  */
78 void drm_release_iommu_mapping(struct drm_device *drm_dev)
79 {
80         struct device *dev = drm_dev->dev;
81
82         arm_iommu_release_mapping(dev->archdata.mapping);
83 }
84
85 /*
86  * drm_iommu_attach_device- attach device to iommu mapping
87  *
88  * @drm_dev: DRM device
89  * @subdrv_dev: device to be attach
90  *
91  * This function should be called by sub drivers to attach it to iommu
92  * mapping.
93  */
94 int drm_iommu_attach_device(struct drm_device *drm_dev,
95                                 struct device *subdrv_dev)
96 {
97         struct device *dev = drm_dev->dev;
98         int ret;
99
100         if (!dev->archdata.mapping) {
101                 DRM_ERROR("iommu_mapping is null.\n");
102                 return -EFAULT;
103         }
104
105         subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev,
106                                         sizeof(*subdrv_dev->dma_parms),
107                                         GFP_KERNEL);
108         dma_set_max_seg_size(subdrv_dev, 0xffffffffu);
109
110         ret = arm_iommu_attach_device(subdrv_dev, dev->archdata.mapping);
111         if (ret < 0) {
112                 DRM_DEBUG_KMS("failed iommu attach.\n");
113                 return ret;
114         }
115
116         /*
117          * Set dma_ops to drm_device just one time.
118          *
119          * The dma mapping api needs device object and the api is used
120          * to allocate physial memory and map it with iommu table.
121          * If iommu attach succeeded, the sub driver would have dma_ops
122          * for iommu and also all sub drivers have same dma_ops.
123          */
124         if (!dev->archdata.dma_ops)
125                 dev->archdata.dma_ops = subdrv_dev->archdata.dma_ops;
126
127         return 0;
128 }
129
130 /*
131  * drm_iommu_detach_device -detach device address space mapping from device
132  *
133  * @drm_dev: DRM device
134  * @subdrv_dev: device to be detached
135  *
136  * This function should be called by sub drivers to detach it from iommu
137  * mapping
138  */
139 void drm_iommu_detach_device(struct drm_device *drm_dev,
140                                 struct device *subdrv_dev)
141 {
142         struct device *dev = drm_dev->dev;
143         struct dma_iommu_mapping *mapping = dev->archdata.mapping;
144
145         if (!mapping || !mapping->domain)
146                 return;
147
148         iommu_detach_device(mapping->domain, subdrv_dev);
149         drm_release_iommu_mapping(drm_dev);
150 }