blob: 1e82529e0c41558a0a6ced31aa16d2a38699f892 [file] [log] [blame]
Inki Dae0519f9a2012-10-20 07:53:42 -07001/* exynos_drm_iommu.c
2 *
3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * Author: Inki Dae <inki.dae@samsung.com>
5 *
Inki Daed81aecb2012-12-18 02:30:17 +09006 * 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.
Inki Dae0519f9a2012-10-20 07:53:42 -070010 */
11
Andrzej Hajda4e6319c2016-02-24 15:15:22 +010012#include <drm/drmP.h>
Inki Dae0519f9a2012-10-20 07:53:42 -070013#include <drm/exynos_drm.h>
14
15#include <linux/dma-mapping.h>
16#include <linux/iommu.h>
17#include <linux/kref.h>
18
19#include <asm/dma-iommu.h>
20
21#include "exynos_drm_drv.h"
22#include "exynos_drm_iommu.h"
23
Marek Szyprowskif7c72772016-06-17 09:54:23 +020024static inline int configure_dma_max_seg_size(struct device *dev)
25{
26 if (!dev->dma_parms)
27 dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
28 if (!dev->dma_parms)
29 return -ENOMEM;
30
31 dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
32 return 0;
33}
34
35static inline void clear_dma_max_seg_size(struct device *dev)
36{
37 kfree(dev->dma_parms);
38 dev->dma_parms = NULL;
39}
40
Inki Dae0519f9a2012-10-20 07:53:42 -070041/*
42 * drm_create_iommu_mapping - create a mapping structure
43 *
44 * @drm_dev: DRM device
45 */
46int drm_create_iommu_mapping(struct drm_device *drm_dev)
47{
48 struct dma_iommu_mapping *mapping = NULL;
49 struct exynos_drm_private *priv = drm_dev->dev_private;
Inki Dae0519f9a2012-10-20 07:53:42 -070050
51 if (!priv->da_start)
52 priv->da_start = EXYNOS_DEV_ADDR_START;
53 if (!priv->da_space_size)
54 priv->da_space_size = EXYNOS_DEV_ADDR_SIZE;
Inki Dae0519f9a2012-10-20 07:53:42 -070055
56 mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start,
Marek Szyprowski68efd7d2014-02-25 13:01:09 +010057 priv->da_space_size);
58
Wei Yongjuna0e41b52012-12-10 02:11:13 -050059 if (IS_ERR(mapping))
60 return PTR_ERR(mapping);
Inki Dae0519f9a2012-10-20 07:53:42 -070061
Marek Szyprowskif43c3592016-02-29 17:50:53 +090062 priv->mapping = mapping;
Inki Dae0519f9a2012-10-20 07:53:42 -070063
64 return 0;
65}
66
67/*
68 * drm_release_iommu_mapping - release iommu mapping structure
69 *
70 * @drm_dev: DRM device
71 *
72 * if mapping->kref becomes 0 then all things related to iommu mapping
73 * will be released
74 */
75void drm_release_iommu_mapping(struct drm_device *drm_dev)
76{
Marek Szyprowskif43c3592016-02-29 17:50:53 +090077 struct exynos_drm_private *priv = drm_dev->dev_private;
Inki Dae0519f9a2012-10-20 07:53:42 -070078
Marek Szyprowskif43c3592016-02-29 17:50:53 +090079 arm_iommu_release_mapping(priv->mapping);
Inki Dae0519f9a2012-10-20 07:53:42 -070080}
81
82/*
83 * drm_iommu_attach_device- attach device to iommu mapping
84 *
85 * @drm_dev: DRM device
86 * @subdrv_dev: device to be attach
87 *
88 * This function should be called by sub drivers to attach it to iommu
89 * mapping.
90 */
91int drm_iommu_attach_device(struct drm_device *drm_dev,
92 struct device *subdrv_dev)
93{
Marek Szyprowskif43c3592016-02-29 17:50:53 +090094 struct exynos_drm_private *priv = drm_dev->dev_private;
Inki Dae0519f9a2012-10-20 07:53:42 -070095 int ret;
96
Marek Szyprowskif43c3592016-02-29 17:50:53 +090097 if (!priv->mapping)
Joonyoung Shimbf566082015-07-02 21:49:38 +090098 return 0;
Inki Dae0519f9a2012-10-20 07:53:42 -070099
Sachin Kamat4db7fcd2013-08-14 16:38:03 +0530100
Marek Szyprowskif7c72772016-06-17 09:54:23 +0200101 ret = configure_dma_max_seg_size(subdrv_dev);
102 if (ret)
103 return ret;
Inki Dae0519f9a2012-10-20 07:53:42 -0700104
Marek Szyprowski45286852015-06-03 10:26:23 +0200105 if (subdrv_dev->archdata.mapping)
106 arm_iommu_detach_device(subdrv_dev);
107
Marek Szyprowskif43c3592016-02-29 17:50:53 +0900108 ret = arm_iommu_attach_device(subdrv_dev, priv->mapping);
Inki Dae0519f9a2012-10-20 07:53:42 -0700109 if (ret < 0) {
110 DRM_DEBUG_KMS("failed iommu attach.\n");
Marek Szyprowskif7c72772016-06-17 09:54:23 +0200111 clear_dma_max_seg_size(subdrv_dev);
Inki Dae0519f9a2012-10-20 07:53:42 -0700112 return ret;
113 }
114
Inki Dae0519f9a2012-10-20 07:53:42 -0700115 return 0;
116}
117
118/*
119 * drm_iommu_detach_device -detach device address space mapping from device
120 *
121 * @drm_dev: DRM device
122 * @subdrv_dev: device to be detached
123 *
124 * This function should be called by sub drivers to detach it from iommu
125 * mapping
126 */
127void drm_iommu_detach_device(struct drm_device *drm_dev,
128 struct device *subdrv_dev)
129{
Marek Szyprowskif43c3592016-02-29 17:50:53 +0900130 struct exynos_drm_private *priv = drm_dev->dev_private;
131 struct dma_iommu_mapping *mapping = priv->mapping;
Inki Dae0519f9a2012-10-20 07:53:42 -0700132
133 if (!mapping || !mapping->domain)
134 return;
135
Joonyoung Shim4d91a852015-10-02 09:30:38 +0900136 arm_iommu_detach_device(subdrv_dev);
Marek Szyprowskif7c72772016-06-17 09:54:23 +0200137 clear_dma_max_seg_size(subdrv_dev);
Inki Dae0519f9a2012-10-20 07:53:42 -0700138}