exynos_drm_iommu.h 3.5 KB
Newer Older
1 2 3 4 5
/* exynos_drm_iommu.h
 *
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 * Authoer: Inki Dae <inki.dae@samsung.com>
 *
6 7 8 9
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
10 11 12 13 14 15 16 17 18 19
 */

#ifndef _EXYNOS_DRM_IOMMU_H_
#define _EXYNOS_DRM_IOMMU_H_

#define EXYNOS_DEV_ADDR_START	0x20000000
#define EXYNOS_DEV_ADDR_SIZE	0x40000000

#ifdef CONFIG_DRM_EXYNOS_IOMMU

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
#if defined(CONFIG_ARM_DMA_USE_IOMMU)
#include <asm/dma-iommu.h>

static inline int __exynos_iommu_create_mapping(struct exynos_drm_private *priv,
					unsigned long start, unsigned long size)
{
	priv->mapping = arm_iommu_create_mapping(&platform_bus_type, start,
						 size);
	return IS_ERR(priv->mapping);
}

static inline void
__exynos_iommu_release_mapping(struct exynos_drm_private *priv)
{
	arm_iommu_release_mapping(priv->mapping);
}

static inline int __exynos_iommu_attach(struct exynos_drm_private *priv,
					struct device *dev)
{
	if (dev->archdata.mapping)
		arm_iommu_detach_device(dev);

	return arm_iommu_attach_device(dev, priv->mapping);
}

static inline void __exynos_iommu_detach(struct exynos_drm_private *priv,
					 struct device *dev)
{
	arm_iommu_detach_device(dev);
}

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#elif defined(CONFIG_IOMMU_DMA)
#include <linux/dma-iommu.h>

static inline int __exynos_iommu_create_mapping(struct exynos_drm_private *priv,
					unsigned long start, unsigned long size)
{
	struct iommu_domain *domain;
	int ret;

	domain = iommu_domain_alloc(priv->dma_dev->bus);
	if (!domain)
		return -ENOMEM;

	ret = iommu_get_dma_cookie(domain);
	if (ret)
		goto free_domain;

	ret = iommu_dma_init_domain(domain, start, size);
	if (ret)
		goto put_cookie;

	priv->mapping = domain;
	return 0;

put_cookie:
	iommu_put_dma_cookie(domain);
free_domain:
	iommu_domain_free(domain);
	return ret;
}

static inline void __exynos_iommu_release_mapping(struct exynos_drm_private *priv)
{
	struct iommu_domain *domain = priv->mapping;

	iommu_put_dma_cookie(domain);
	iommu_domain_free(domain);
	priv->mapping = NULL;
}

static inline int __exynos_iommu_attach(struct exynos_drm_private *priv,
					struct device *dev)
{
	struct iommu_domain *domain = priv->mapping;

	return iommu_attach_device(domain, dev);
}

static inline void __exynos_iommu_detach(struct exynos_drm_private *priv,
					 struct device *dev)
{
	struct iommu_domain *domain = priv->mapping;

	iommu_detach_device(domain, dev);
}
107 108 109 110
#else
#error Unsupported architecture and IOMMU/DMA-mapping glue code
#endif

111 112 113 114 115 116 117 118 119 120 121 122
int drm_create_iommu_mapping(struct drm_device *drm_dev);

void drm_release_iommu_mapping(struct drm_device *drm_dev);

int drm_iommu_attach_device(struct drm_device *drm_dev,
				struct device *subdrv_dev);

void drm_iommu_detach_device(struct drm_device *dev_dev,
				struct device *subdrv_dev);

static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
{
123
	struct exynos_drm_private *priv = drm_dev->dev_private;
124

125
	return priv->mapping ? true : false;
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
}

#else

static inline int drm_create_iommu_mapping(struct drm_device *drm_dev)
{
	return 0;
}

static inline void drm_release_iommu_mapping(struct drm_device *drm_dev)
{
}

static inline int drm_iommu_attach_device(struct drm_device *drm_dev,
						struct device *subdrv_dev)
{
	return 0;
}

static inline void drm_iommu_detach_device(struct drm_device *drm_dev,
						struct device *subdrv_dev)
{
}

static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
{
	return false;
}

#endif
#endif