1 /* sunxi_drm_iommu.h
2 *
3 * Copyright (C) 2022 Allwinnertech Co., Ltd.
4 * Authors: hongyaobin <hongyaobin@allwinnertech.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12 #ifndef _SUNXI_DRM_IOMMU_H_
13 #define _SUNXI_DRM_IOMMU_H_
14
15 #ifdef CONFIG_AW_DRM_IOMMU
16
17 #if defined(CONFIG_ARM_DMA_USE_IOMMU)
18 #include <asm/dma-iommu.h>
19
__sunxi_iommu_create_mapping(struct sunxi_drm_private * priv,unsigned long start,unsigned long size)20 static inline int __sunxi_iommu_create_mapping(struct sunxi_drm_private *priv,
21 unsigned long start, unsigned long size)
22 {
23 DRM_INFO("[DRM-DRV] %s:arm_iommu_create_mapping\n", __func__);
24 priv->mapping = arm_iommu_create_mapping(&platform_bus_type, start,
25 size);
26 return IS_ERR(priv->mapping);
27 }
28
29 static inline void
__sunxi_iommu_release_mapping(struct sunxi_drm_private * priv)30 __sunxi_iommu_release_mapping(struct sunxi_drm_private *priv)
31 {
32 arm_iommu_release_mapping(priv->mapping);
33 }
34
__sunxi_iommu_attach(struct sunxi_drm_private * priv,struct device * dev)35 static inline int __sunxi_iommu_attach(struct sunxi_drm_private *priv,
36 struct device *dev)
37 {
38 if (dev->archdata.mapping)
39 arm_iommu_detach_device(dev);
40
41 return arm_iommu_attach_device(dev, priv->mapping);
42 }
43
__sunxi_iommu_detach(struct sunxi_drm_private * priv,struct device * dev)44 static inline void __sunxi_iommu_detach(struct sunxi_drm_private *priv,
45 struct device *dev)
46 {
47 arm_iommu_detach_device(dev);
48 }
49
50 #elif defined(CONFIG_IOMMU_DMA)
51 #include <linux/dma-iommu.h>
52
__sunxi_iommu_create_mapping(struct sunxi_drm_private * priv,unsigned long start,unsigned long size)53 static inline int __sunxi_iommu_create_mapping(struct sunxi_drm_private *priv,
54 unsigned long start, unsigned long size)
55 {
56 DRM_INFO("[DRM-DRV] %s\n", __func__);
57 priv->mapping = iommu_get_domain_for_dev(priv->drm_dev->dev);
58 if (priv->mapping == NULL)
59 return -1;
60 else
61 return 0;
62 }
63
__sunxi_iommu_release_mapping(struct sunxi_drm_private * priv)64 static inline void __sunxi_iommu_release_mapping(struct sunxi_drm_private *priv)
65 {
66 priv->mapping = NULL;
67 }
68
__sunxi_iommu_attach(struct sunxi_drm_private * priv,struct device * dev)69 static inline int __sunxi_iommu_attach(struct sunxi_drm_private *priv,
70 struct device *dev)
71 {
72 struct iommu_domain *domain = priv->mapping;
73
74 if (dev != priv->drm_dev->dev)
75 return iommu_attach_device(domain, dev);
76 return 0;
77 }
78
__sunxi_iommu_detach(struct sunxi_drm_private * priv,struct device * dev)79 static inline void __sunxi_iommu_detach(struct sunxi_drm_private *priv,
80 struct device *dev)
81 {
82 struct iommu_domain *domain = priv->mapping;
83
84 if (dev != priv->drm_dev->dev)
85 iommu_detach_device(domain, dev);
86 }
87 #else
88 #error Unsupported architecture and IOMMU/DMA-mapping glue code
89 #endif
90
91 int sunxi_drm_create_iommu_mapping(struct drm_device *drm_dev);
92
93 void sunxi_drm_release_iommu_mapping(struct drm_device *drm_dev);
94
95 int sunxi_drm_iommu_attach_device(struct drm_device *drm_dev,
96 struct device *subdrv_dev);
97
98 void sunxi_drm_iommu_detach_device(struct drm_device *dev_dev,
99 struct device *subdrv_dev);
100
is_drm_iommu_supported(struct drm_device * drm_dev)101 static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
102 {
103 struct sunxi_drm_private *priv = drm_dev->dev_private;
104
105 return priv->mapping ? true : false;
106 }
107
108 #else
109
sunxi_drm_create_iommu_mapping(struct drm_device * drm_dev)110 static inline int sunxi_drm_create_iommu_mapping(struct drm_device *drm_dev)
111 {
112 return 0;
113 }
114
sunxi_drm_release_iommu_mapping(struct drm_device * drm_dev)115 static inline void sunxi_drm_release_iommu_mapping(struct drm_device *drm_dev)
116 {
117 }
118
sunxi_drm_iommu_attach_device(struct drm_device * drm_dev,struct device * subdrv_dev)119 static inline int sunxi_drm_iommu_attach_device(struct drm_device *drm_dev,
120 struct device *subdrv_dev)
121 {
122 return 0;
123 }
124
sunxi_drm_iommu_detach_device(struct drm_device * drm_dev,struct device * subdrv_dev)125 static inline void sunxi_drm_iommu_detach_device(struct drm_device *drm_dev,
126 struct device *subdrv_dev)
127 {
128 }
129
is_drm_iommu_supported(struct drm_device * drm_dev)130 static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
131 {
132 return false;
133 }
134
135 #endif
136 #endif
137