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 <jay.xu@rock-chips.com>
Signed-off-by: Felix Zeng <felix.zeng@rock-chips.com>
This commit is contained in:
Jianqun Xu
2021-08-23 14:22:03 +08:00
committed by Tao Huang
parent c7641517d1
commit e649ca006e
3 changed files with 54 additions and 6 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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;