From e649ca006e7013bccffc64cc11524692038174dd Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 23 Aug 2021 14:22:03 +0800 Subject: [PATCH] rknpu: add fake platform device to rknpu device The device 'fake_dev' under rknpu_dev is registered by rknpu_drv, which is a virtual platform device. The rknpu partial sync should use a platform device without iommu, so to use rknpu_dev->fake_dev. Change-Id: I33f1b05d308063f235d31044f8e562755c1217f4 Signed-off-by: Jianqun Xu Signed-off-by: Felix Zeng --- drivers/rknpu/include/rknpu_drv.h | 2 ++ drivers/rknpu/rknpu_drv.c | 42 +++++++++++++++++++++++++++++++ drivers/rknpu/rknpu_gem.c | 16 +++++++----- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/drivers/rknpu/include/rknpu_drv.h b/drivers/rknpu/include/rknpu_drv.h index 84623a271a56..9683aa65f868 100644 --- a/drivers/rknpu/include/rknpu_drv.h +++ b/drivers/rknpu/include/rknpu_drv.h @@ -40,6 +40,7 @@ struct rknpu_config { __u32 bw_priority_base; __u32 bw_priority_length; + __u64 dma_mask; }; /** @@ -52,6 +53,7 @@ struct rknpu_config { struct rknpu_device { void __iomem *base; struct device *dev; + struct device *fake_dev; struct drm_device *drm_dev; atomic_t sequence; spinlock_t lock; diff --git a/drivers/rknpu/rknpu_drv.c b/drivers/rknpu/rknpu_drv.c index c1e1134422f2..c6d3fb9b3e8f 100644 --- a/drivers/rknpu/rknpu_drv.c +++ b/drivers/rknpu/rknpu_drv.c @@ -49,6 +49,7 @@ MODULE_PARM_DESC(bypass_irq_handler, static const struct rknpu_config rk356x_rknpu_config = { .bw_priority_base = 0xfe180008, .bw_priority_length = 0x10, + .dma_mask = DMA_BIT_MASK(32), }; /* driver probe and init */ @@ -247,6 +248,42 @@ static bool rknpu_is_iommu_enable(struct device *dev) return true; } +static int drm_fake_dev_register(struct rknpu_device *rknpu_dev) +{ + const struct platform_device_info rknpu_dev_info = { + .name = "rknpu_dev", + .id = PLATFORM_DEVID_AUTO, + .dma_mask = rknpu_dev->config->dma_mask, + }; + struct platform_device *pdev = NULL; + int ret = -EINVAL; + + pdev = platform_device_register_full(&rknpu_dev_info); + if (pdev) { + ret = of_dma_configure(&pdev->dev, NULL, true); + if (ret) { + platform_device_unregister(pdev); + pdev = NULL; + } + } + + rknpu_dev->fake_dev = pdev ? &pdev->dev : NULL; + + return ret; +} + +static void drm_fake_dev_unregister(struct rknpu_device *rknpu_dev) +{ + struct platform_device *pdev = NULL; + + if (!rknpu_dev->fake_dev) + return; + + pdev = to_platform_device(rknpu_dev->fake_dev); + + platform_device_unregister(pdev); +} + static int rknpu_drm_probe(struct rknpu_device *rknpu_dev) { struct device *dev = rknpu_dev->dev; @@ -265,6 +302,8 @@ static int rknpu_drm_probe(struct rknpu_device *rknpu_dev) drm_dev->dev_private = rknpu_dev; rknpu_dev->drm_dev = drm_dev; + drm_fake_dev_register(rknpu_dev); + return 0; err_free_drm: @@ -281,7 +320,10 @@ static void rknpu_drm_remove(struct rknpu_device *rknpu_dev) { struct drm_device *drm_dev = rknpu_dev->drm_dev; + drm_fake_dev_unregister(rknpu_dev); + drm_dev_unregister(drm_dev); + #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE drm_dev_put(drm_dev); #else diff --git a/drivers/rknpu/rknpu_gem.c b/drivers/rknpu/rknpu_gem.c index 5f4d6ff99472..45045723eb22 100644 --- a/drivers/rknpu/rknpu_gem.c +++ b/drivers/rknpu/rknpu_gem.c @@ -935,6 +935,11 @@ int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data, DMA_FROM_DEVICE); } } else { + struct drm_device *drm = rknpu_obj->base.dev; + struct rknpu_device *rknpu_dev = drm->dev_private; + + WARN_ON(!rknpu_dev->fake_dev); + length = args->size; offset = args->offset; @@ -951,15 +956,14 @@ int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data, if (args->flags & RKNPU_MEM_SYNC_TO_DEVICE) { dma_sync_single_range_for_device( - dev->dev, sg_dma_addr, sg_offset, size, - DMA_TO_DEVICE); + rknpu_dev->fake_dev, sg_dma_addr, + sg_offset, size, DMA_TO_DEVICE); } if (args->flags & RKNPU_MEM_SYNC_FROM_DEVICE) { - dma_sync_single_range_for_cpu(dev->dev, - sg_dma_addr, - sg_offset, size, - DMA_FROM_DEVICE); + dma_sync_single_range_for_cpu( + rknpu_dev->fake_dev, sg_dma_addr, + sg_offset, size, DMA_FROM_DEVICE); } offset += size;