Skip to content

Commit

Permalink
Merge branch 'drm-rockchip-next-2017-02-16' of https://github.com/mar…
Browse files Browse the repository at this point in the history
…kyzq/kernel-drm-rockchip into drm-next

Use iommu for rockchip arm64 platform.

* 'drm-rockchip-next-2017-02-16' of https://github.com/markyzq/kernel-drm-rockchip:
  drm/rockchip: Use common IOMMU API to attach devices
  drm/rockchip: Do not use DMA mapping API if attached to IOMMU domain
  • Loading branch information
Dave Airlie committed Feb 16, 2017
2 parents b7bc0da + 1aa5ca6 commit be3c9f5
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 61 deletions.
101 changes: 54 additions & 47 deletions drivers/gpu/drm/rockchip/rockchip_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
* GNU General Public License for more details.
*/

#include <asm/dma-iommu.h>

#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_of.h>
#include <linux/dma-mapping.h>
#include <linux/dma-iommu.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/component.h>
#include <linux/console.h>
#include <linux/iommu.h>

#include "rockchip_drm_drv.h"
#include "rockchip_drm_fb.h"
Expand All @@ -50,28 +50,31 @@ static struct drm_driver rockchip_drm_driver;
int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
struct device *dev)
{
struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
struct rockchip_drm_private *private = drm_dev->dev_private;
int ret;

if (!is_support_iommu)
return 0;

ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
if (ret)
ret = iommu_attach_device(private->domain, dev);
if (ret) {
dev_err(dev, "Failed to attach iommu device\n");
return ret;
}

dma_set_max_seg_size(dev, DMA_BIT_MASK(32));

return arm_iommu_attach_device(dev, mapping);
return 0;
}

void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
{
struct rockchip_drm_private *private = drm_dev->dev_private;
struct iommu_domain *domain = private->domain;

if (!is_support_iommu)
return;

arm_iommu_detach_device(dev);
iommu_detach_device(domain, dev);
}

int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
Expand Down Expand Up @@ -123,11 +126,46 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
}

static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
{
struct rockchip_drm_private *private = drm_dev->dev_private;
struct iommu_domain_geometry *geometry;
u64 start, end;

if (!is_support_iommu)
return 0;

private->domain = iommu_domain_alloc(&platform_bus_type);
if (!private->domain)
return -ENOMEM;

geometry = &private->domain->geometry;
start = geometry->aperture_start;
end = geometry->aperture_end;

DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
start, end);
drm_mm_init(&private->mm, start, end - start + 1);
mutex_init(&private->mm_lock);

return 0;
}

static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
{
struct rockchip_drm_private *private = drm_dev->dev_private;

if (!is_support_iommu)
return;

drm_mm_takedown(&private->mm);
iommu_domain_free(private->domain);
}

static int rockchip_drm_bind(struct device *dev)
{
struct drm_device *drm_dev;
struct rockchip_drm_private *private;
struct dma_iommu_mapping *mapping = NULL;
int ret;

drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);
Expand All @@ -151,38 +189,14 @@ static int rockchip_drm_bind(struct device *dev)

rockchip_drm_mode_config_init(drm_dev);

dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
GFP_KERNEL);
if (!dev->dma_parms) {
ret = -ENOMEM;
ret = rockchip_drm_init_iommu(drm_dev);
if (ret)
goto err_config_cleanup;
}

if (is_support_iommu) {
/* TODO(djkurtz): fetch the mapping start/size from somewhere */
mapping = arm_iommu_create_mapping(&platform_bus_type,
0x00000000,
SZ_2G);
if (IS_ERR(mapping)) {
ret = PTR_ERR(mapping);
goto err_config_cleanup;
}

ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
goto err_release_mapping;

dma_set_max_seg_size(dev, DMA_BIT_MASK(32));

ret = arm_iommu_attach_device(dev, mapping);
if (ret)
goto err_release_mapping;
}

/* Try to bind all sub drivers. */
ret = component_bind_all(dev, drm_dev);
if (ret)
goto err_detach_device;
goto err_iommu_cleanup;

/* init kms poll for handling hpd */
drm_kms_helper_poll_init(drm_dev);
Expand All @@ -207,8 +221,6 @@ static int rockchip_drm_bind(struct device *dev)
if (ret)
goto err_fbdev_fini;

if (is_support_iommu)
arm_iommu_release_mapping(mapping);
return 0;
err_fbdev_fini:
rockchip_drm_fbdev_fini(drm_dev);
Expand All @@ -217,12 +229,8 @@ static int rockchip_drm_bind(struct device *dev)
err_kms_helper_poll_fini:
drm_kms_helper_poll_fini(drm_dev);
component_unbind_all(dev, drm_dev);
err_detach_device:
if (is_support_iommu)
arm_iommu_detach_device(dev);
err_release_mapping:
if (is_support_iommu)
arm_iommu_release_mapping(mapping);
err_iommu_cleanup:
rockchip_iommu_cleanup(drm_dev);
err_config_cleanup:
drm_mode_config_cleanup(drm_dev);
drm_dev->dev_private = NULL;
Expand All @@ -239,8 +247,7 @@ static void rockchip_drm_unbind(struct device *dev)
drm_vblank_cleanup(drm_dev);
drm_kms_helper_poll_fini(drm_dev);
component_unbind_all(dev, drm_dev);
if (is_support_iommu)
arm_iommu_detach_device(dev);
rockchip_iommu_cleanup(drm_dev);
drm_mode_config_cleanup(drm_dev);
drm_dev->dev_private = NULL;
drm_dev_unregister(drm_dev);
Expand Down
6 changes: 5 additions & 1 deletion drivers/gpu/drm/rockchip/rockchip_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

struct drm_device;
struct drm_connector;
struct iommu_domain;

/*
* Rockchip drm private crtc funcs.
Expand Down Expand Up @@ -60,7 +61,10 @@ struct rockchip_drm_private {
struct drm_gem_object *fbdev_bo;
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
struct drm_atomic_state *state;

struct iommu_domain *domain;
/* protect drm_mm on multi-threads */
struct mutex mm_lock;
struct drm_mm mm;
struct list_head psr_list;
spinlock_t psr_list_lock;
};
Expand Down
Loading

0 comments on commit be3c9f5

Please sign in to comment.