2012-10-20 07:53:42 -07:00
/* exynos_drm_iommu.c
*
* Copyright ( c ) 2012 Samsung Electronics Co . , Ltd .
* Author : Inki Dae < inki . dae @ samsung . com >
*
2012-12-18 02:30:17 +09:00
* 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 .
2012-10-20 07:53:42 -07:00
*/
2016-02-24 15:15:22 +01:00
# include <drm/drmP.h>
2012-10-20 07:53:42 -07:00
# include <drm/exynos_drm.h>
# include <linux/dma-mapping.h>
# include <linux/iommu.h>
# include "exynos_drm_drv.h"
# include "exynos_drm_iommu.h"
2016-06-17 09:54:23 +02:00
static inline int configure_dma_max_seg_size ( struct device * dev )
{
if ( ! dev - > dma_parms )
dev - > dma_parms = kzalloc ( sizeof ( * dev - > dma_parms ) , GFP_KERNEL ) ;
if ( ! dev - > dma_parms )
return - ENOMEM ;
dma_set_max_seg_size ( dev , DMA_BIT_MASK ( 32 ) ) ;
return 0 ;
}
static inline void clear_dma_max_seg_size ( struct device * dev )
{
kfree ( dev - > dma_parms ) ;
dev - > dma_parms = NULL ;
}
2012-10-20 07:53:42 -07:00
/*
* drm_create_iommu_mapping - create a mapping structure
*
* @ drm_dev : DRM device
*/
int drm_create_iommu_mapping ( struct drm_device * drm_dev )
{
struct exynos_drm_private * priv = drm_dev - > dev_private ;
2016-06-17 09:54:26 +02:00
return __exynos_iommu_create_mapping ( priv , EXYNOS_DEV_ADDR_START ,
EXYNOS_DEV_ADDR_SIZE ) ;
2012-10-20 07:53:42 -07:00
}
/*
* drm_release_iommu_mapping - release iommu mapping structure
*
* @ drm_dev : DRM device
*/
void drm_release_iommu_mapping ( struct drm_device * drm_dev )
{
2016-02-29 17:50:53 +09:00
struct exynos_drm_private * priv = drm_dev - > dev_private ;
2012-10-20 07:53:42 -07:00
2016-06-17 09:54:26 +02:00
__exynos_iommu_release_mapping ( priv ) ;
2012-10-20 07:53:42 -07:00
}
/*
* drm_iommu_attach_device - attach device to iommu mapping
*
* @ drm_dev : DRM device
* @ subdrv_dev : device to be attach
*
* This function should be called by sub drivers to attach it to iommu
* mapping .
*/
int drm_iommu_attach_device ( struct drm_device * drm_dev ,
struct device * subdrv_dev )
{
2016-02-29 17:50:53 +09:00
struct exynos_drm_private * priv = drm_dev - > dev_private ;
2012-10-20 07:53:42 -07:00
int ret ;
2016-06-17 09:54:24 +02:00
if ( get_dma_ops ( priv - > dma_dev ) ! = get_dma_ops ( subdrv_dev ) ) {
DRM_ERROR ( " Device %s lacks support for IOMMU \n " ,
dev_name ( subdrv_dev ) ) ;
return - EINVAL ;
}
2013-08-14 16:38:03 +05:30
2016-06-17 09:54:23 +02:00
ret = configure_dma_max_seg_size ( subdrv_dev ) ;
if ( ret )
return ret ;
2012-10-20 07:53:42 -07:00
2016-06-17 09:54:26 +02:00
ret = __exynos_iommu_attach ( priv , subdrv_dev ) ;
if ( ret )
2016-06-17 09:54:23 +02:00
clear_dma_max_seg_size ( subdrv_dev ) ;
2012-10-20 07:53:42 -07:00
return 0 ;
}
/*
* drm_iommu_detach_device - detach device address space mapping from device
*
* @ drm_dev : DRM device
* @ subdrv_dev : device to be detached
*
* This function should be called by sub drivers to detach it from iommu
* mapping
*/
void drm_iommu_detach_device ( struct drm_device * drm_dev ,
struct device * subdrv_dev )
{
2016-02-29 17:50:53 +09:00
struct exynos_drm_private * priv = drm_dev - > dev_private ;
2012-10-20 07:53:42 -07:00
2016-06-17 09:54:26 +02:00
__exynos_iommu_detach ( priv , subdrv_dev ) ;
2016-06-17 09:54:23 +02:00
clear_dma_max_seg_size ( subdrv_dev ) ;
2012-10-20 07:53:42 -07:00
}