From 3d588e4c36ee56eb7fb1560f094b8f0235d6f6ff Mon Sep 17 00:00:00 2001 From: Felix Zeng Date: Wed, 17 Nov 2021 14:58:59 +0800 Subject: [PATCH] driver: rknpu: Update rknpu driver, version: 0.6.4 * Add support for rk3588/rk3588s Signed-off-by: Felix Zeng Change-Id: I292cca4037367d21e88f05bb8a8b7cac93c2f91e --- drivers/rknpu/include/rknpu_drv.h | 34 ++- drivers/rknpu/include/rknpu_fence.h | 4 +- drivers/rknpu/include/rknpu_ioctl.h | 27 +- drivers/rknpu/include/rknpu_job.h | 21 +- drivers/rknpu/rknpu_drv.c | 213 ++++++++++----- drivers/rknpu/rknpu_fence.c | 17 +- drivers/rknpu/rknpu_gem.c | 7 +- drivers/rknpu/rknpu_job.c | 397 +++++++++++++++++++++++----- drivers/rknpu/rknpu_reset.c | 47 ++-- 9 files changed, 588 insertions(+), 179 deletions(-) diff --git a/drivers/rknpu/include/rknpu_drv.h b/drivers/rknpu/include/rknpu_drv.h index eea0cc64fd4c..44c68d733cd0 100644 --- a/drivers/rknpu/include/rknpu_drv.h +++ b/drivers/rknpu/include/rknpu_drv.h @@ -20,10 +20,10 @@ #define DRIVER_NAME "rknpu" #define DRIVER_DESC "RKNPU driver" -#define DRIVER_DATE "20210824" +#define DRIVER_DATE "20211227" #define DRIVER_MAJOR 0 -#define DRIVER_MINOR 5 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_MINOR 6 +#define DRIVER_PATCHLEVEL 4 #define LOG_TAG "RKNPU" @@ -42,10 +42,28 @@ DRM_DEV_DEBUG_DRIVER(dev, LOG_TAG ": " fmt, ##args) #define LOG_DEV_ERROR(dev, fmt, args...) dev_err(dev, LOG_TAG ": " fmt, ##args) +struct npu_reset_data { + const char *srst_a_name; + const char *srst_h_name; +}; + struct rknpu_config { __u32 bw_priority_addr; __u32 bw_priority_length; __u64 dma_mask; + __u32 pc_data_extra_amount; + __u32 bw_enable; + const struct npu_irqs_data *irqs; + const struct npu_reset_data *resets; + int num_irqs; + int num_resets; +}; + +struct rknpu_subcore_data { + struct list_head todo_list; + wait_queue_head_t job_done_wq; + struct rknpu_job *job; + uint64_t task_num; }; /** @@ -56,22 +74,20 @@ struct rknpu_config { * @drm_dev: DRM device instance */ struct rknpu_device { - void __iomem *base; + void __iomem *base[RKNPU_MAX_CORES]; struct device *dev; struct device *fake_dev; struct drm_device *drm_dev; atomic_t sequence; spinlock_t lock; spinlock_t irq_lock; - struct list_head todo_list; - wait_queue_head_t job_done_wq; + struct rknpu_subcore_data subcore_datas[RKNPU_MAX_CORES]; const struct rknpu_config *config; void __iomem *bw_priority_base; - struct rknpu_job *job; struct rknpu_fence_context *fence_ctx; bool iommu_en; - struct reset_control *srst_a; - struct reset_control *srst_h; + struct reset_control *srst_a[RKNPU_MAX_CORES]; + struct reset_control *srst_h[RKNPU_MAX_CORES]; struct clk_bulk_data *clks; int num_clks; struct regulator *vdd; diff --git a/drivers/rknpu/include/rknpu_fence.h b/drivers/rknpu/include/rknpu_fence.h index 53047ad0b6a4..c0f9d73e107a 100644 --- a/drivers/rknpu/include/rknpu_fence.h +++ b/drivers/rknpu/include/rknpu_fence.h @@ -15,9 +15,7 @@ struct rknpu_fence_context { spinlock_t spinlock; }; -struct rknpu_fence_context *rknpu_fence_context_alloc(void); - -void rknpu_fence_context_free(struct rknpu_fence_context *fence_ctx); +int rknpu_fence_context_alloc(struct rknpu_device *rknpu_dev); int rknpu_fence_alloc(struct rknpu_job *job); diff --git a/drivers/rknpu/include/rknpu_ioctl.h b/drivers/rknpu/include/rknpu_ioctl.h index a6e59b02924e..a63540d46ccd 100644 --- a/drivers/rknpu/include/rknpu_ioctl.h +++ b/drivers/rknpu/include/rknpu_ioctl.h @@ -14,8 +14,6 @@ #define __user #endif -#define RKNPU_PC_DATA_EXTRA_AMOUNT 4 - #define RKNPU_OFFSET_VERSION 0x0 #define RKNPU_OFFSET_PC_OP_EN 0x8 #define RKNPU_OFFSET_PC_DATA_ADDR 0x10 @@ -27,6 +25,7 @@ #define RKNPU_OFFSET_INT_MASK 0x20 #define RKNPU_OFFSET_INT_CLEAR 0x24 #define RKNPU_OFFSET_INT_STATUS 0x28 +#define RKNPU_OFFSET_INT_RAW_STATUS 0x2c #define RKNPU_OFFSET_CLR_ALL_RW_AMOUNT 0x8010 #define RKNPU_OFFSET_DT_WR_AMOUNT 0x8034 @@ -91,9 +90,11 @@ enum e_rknpu_job_mode { RKNPU_JOB_BLOCK = 0 << 1, RKNPU_JOB_NONBLOCK = 1 << 1, RKNPU_JOB_PINGPONG = 1 << 2, - RKNPU_JOB_FENCE = 1 << 3, + RKNPU_JOB_FENCE_IN = 1 << 3, + RKNPU_JOB_FENCE_OUT = 1 << 4, RKNPU_JOB_MASK = RKNPU_JOB_PC | RKNPU_JOB_NONBLOCK | - RKNPU_JOB_PINGPONG | RKNPU_JOB_FENCE + RKNPU_JOB_PINGPONG | RKNPU_JOB_FENCE_IN | + RKNPU_JOB_FENCE_OUT }; /* action definitions */ @@ -206,6 +207,19 @@ struct rknpu_task { __u64 regcmd_data; } __packed; +/** + * struct rknpu_subcore_task structure for subcore task index + * + * @task_start: task start index + * @task_number: task number + * + */ +struct rknpu_subcore_task { + __u32 task_start; + __u32 task_number; + __u32 task_end; +}; + /** * struct rknpu_submit structure for job submit * @@ -219,7 +233,7 @@ struct rknpu_task { * @regcfg_obj_addr: address of register config object * @user_data: (optional) user data * @sequence: submit sequence - * @core_id: core id of rknpu + * @core_mask: core mask of rknpu * @fence_fd: dma fence fd * */ @@ -234,8 +248,9 @@ struct rknpu_submit { __u64 regcfg_obj_addr; __u64 user_data; __u64 sequence; - __u32 core_id; + __u32 core_mask; __s32 fence_fd; + struct rknpu_subcore_task subcore_task[5]; }; /** diff --git a/drivers/rknpu/include/rknpu_job.h b/drivers/rknpu/include/rknpu_job.h index de8846f81bfa..ef3628f8da4b 100644 --- a/drivers/rknpu/include/rknpu_job.h +++ b/drivers/rknpu/include/rknpu_job.h @@ -14,12 +14,19 @@ #include "rknpu_ioctl.h" +#define RKNPU_MAX_CORES 3 + #define RKNPU_JOB_DONE (1 << 0) #define RKNPU_JOB_ASYNC (1 << 1) +#define RKNPU_CORE_AUTO_MASK 0x00 +#define RKNPU_CORE0_MASK 0x01 +#define RKNPU_CORE1_MASK 0x02 +#define RKNPU_CORE2_MASK 0x04 + struct rknpu_job { struct rknpu_device *rknpu_dev; - struct list_head head; + struct list_head head[RKNPU_MAX_CORES]; struct work_struct cleanup_work; unsigned int flags; int ret; @@ -27,14 +34,18 @@ struct rknpu_job { bool args_owner; struct rknpu_task *first_task; struct rknpu_task *last_task; - uint32_t int_mask; - uint32_t int_status; + uint32_t int_mask[RKNPU_MAX_CORES]; + uint32_t int_status[RKNPU_MAX_CORES]; struct dma_fence *fence; - spinlock_t fence_lock; ktime_t timestamp; + uint32_t use_core_num; + uint32_t run_count; + uint32_t interrupt_count; }; -irqreturn_t rknpu_irq_handler(int irq, void *data); +irqreturn_t rknpu_core0_irq_handler(int irq, void *data); +irqreturn_t rknpu_core1_irq_handler(int irq, void *data); +irqreturn_t rknpu_core2_irq_handler(int irq, void *data); int rknpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/rknpu/rknpu_drv.c b/drivers/rknpu/rknpu_drv.c index 2b826271fb1f..9d00eeb956a2 100644 --- a/drivers/rknpu/rknpu_drv.c +++ b/drivers/rknpu/rknpu_drv.c @@ -36,9 +36,11 @@ #include #include +#ifndef FPGA_PLATFORM #include #include #include +#endif #include "rknpu_ioctl.h" #include "rknpu_reset.h" @@ -56,10 +58,52 @@ module_param(bypass_soft_reset, int, 0644); MODULE_PARM_DESC(bypass_soft_reset, "bypass RKNPU soft reset if set it to 1, disabled by default"); +struct npu_irqs_data { + const char *name; + irqreturn_t (*irq_hdl)(int irq, void *ctx); +}; + +static const struct npu_irqs_data rk356x_npu_irqs[] = { + { "npu0_irq", rknpu_core0_irq_handler } +}; + +static const struct npu_irqs_data rk3588_npu_irqs[] = { + { "npu0_irq", rknpu_core0_irq_handler }, + { "npu1_irq", rknpu_core1_irq_handler }, + { "npu2_irq", rknpu_core2_irq_handler } +}; + +static const struct npu_reset_data rk356x_npu_resets[] = { { "srst_a", + "srst_h" } }; + +static const struct npu_reset_data rk3588_npu_resets[] = { + { "srst_a0", "srst_h0" }, + { "srst_a1", "srst_h1" }, + { "srst_a2", "srst_h2" } +}; + static const struct rknpu_config rk356x_rknpu_config = { .bw_priority_addr = 0xfe180008, .bw_priority_length = 0x10, .dma_mask = DMA_BIT_MASK(32), + .pc_data_extra_amount = 4, + .bw_enable = 1, + .irqs = rk356x_npu_irqs, + .resets = rk356x_npu_resets, + .num_irqs = ARRAY_SIZE(rk356x_npu_irqs), + .num_resets = ARRAY_SIZE(rk356x_npu_resets) +}; + +static const struct rknpu_config rk3588_rknpu_config = { + .bw_priority_addr = 0x0, + .bw_priority_length = 0x0, + .dma_mask = DMA_BIT_MASK(40), + .pc_data_extra_amount = 2, + .bw_enable = 0, + .irqs = rk3588_npu_irqs, + .resets = rk3588_npu_resets, + .num_irqs = ARRAY_SIZE(rk3588_npu_irqs), + .num_resets = ARRAY_SIZE(rk3588_npu_resets) }; /* driver probe and init */ @@ -72,6 +116,10 @@ static const struct of_device_id rknpu_of_match[] = { .compatible = "rockchip,rk3568-rknpu", .data = &rk356x_rknpu_config, }, + { + .compatible = "rockchip,rk3588-rknpu", + .data = &rk3588_rknpu_config, + }, {}, }; @@ -350,6 +398,7 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev) struct device *dev = rknpu_dev->dev; int ret = -EINVAL; +#ifndef FPGA_PLATFORM ret = regulator_enable(rknpu_dev->vdd); if (ret) { LOG_DEV_ERROR( @@ -357,6 +406,7 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev) ret); return ret; } +#endif ret = clk_bulk_prepare_enable(rknpu_dev->num_clks, rknpu_dev->clks); if (ret) { @@ -428,11 +478,14 @@ static int rknpu_power_off(struct rknpu_device *rknpu_dev) clk_bulk_disable_unprepare(rknpu_dev->num_clks, rknpu_dev->clks); +#ifndef FPGA_PLATFORM regulator_disable(rknpu_dev->vdd); +#endif return 0; } +#ifndef FPGA_PLATFORM static struct monitor_dev_profile npu_mdevp = { .type = MONITOR_TPYE_DEV, .low_temp_adjust = rockchip_monitor_dev_low_temp_adjust, @@ -677,6 +730,57 @@ static int rknpu_devfreq_init(struct rknpu_device *rknpu_dev) out: return 0; } +#endif + +static int rknpu_register_irq(struct platform_device *pdev, + struct rknpu_device *rknpu_dev) +{ + const struct rknpu_config *config = rknpu_dev->config; + struct device *dev = &pdev->dev; + struct resource *res; + int i, ret, irq; + + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, + config->irqs[0].name); + if (res) { + /* there are irq names in dts */ + for (i = 0; i < config->num_irqs; i++) { + irq = platform_get_irq_byname(pdev, + config->irqs[i].name); + if (irq < 0) { + LOG_DEV_ERROR(dev, "no npu %s in dts\n", + config->irqs[i].name); + return irq; + } + + ret = devm_request_irq(dev, irq, + config->irqs[i].irq_hdl, + IRQF_SHARED, dev_name(dev), + rknpu_dev); + if (ret < 0) { + LOG_DEV_ERROR(dev, "request %s failed: %d\n", + config->irqs[i].name, ret); + return ret; + } + } + } else { + /* no irq names in dts */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + LOG_DEV_ERROR(dev, "no npu irq in dts\n"); + return irq; + } + + ret = devm_request_irq(dev, irq, rknpu_core0_irq_handler, + IRQF_SHARED, dev_name(dev), rknpu_dev); + if (ret < 0) { + LOG_DEV_ERROR(dev, "request irq failed: %d\n", ret); + return ret; + } + } + + return 0; +} static int rknpu_probe(struct platform_device *pdev) { @@ -686,7 +790,7 @@ static int rknpu_probe(struct platform_device *pdev) struct device *virt_dev = NULL; const struct of_device_id *match = NULL; const struct rknpu_config *config = NULL; - int ret = -EINVAL; + int ret = -EINVAL, i = 0; if (!pdev->dev.of_node) { LOG_DEV_ERROR(dev, "rknpu device-tree data is missing!\n"); @@ -729,11 +833,8 @@ static int rknpu_probe(struct platform_device *pdev) rknpu_reset_get(rknpu_dev); rknpu_dev->num_clks = devm_clk_bulk_get_all(dev, &rknpu_dev->clks); - if (rknpu_dev->num_clks < 1) { - LOG_DEV_ERROR(dev, "failed to get clk source for rknpu\n"); - return -ENODEV; - } +#ifndef FPGA_PLATFORM rknpu_dev->vdd = devm_regulator_get_optional(dev, "rknpu"); if (IS_ERR(rknpu_dev->vdd)) { if (PTR_ERR(rknpu_dev->vdd) != -ENODEV) { @@ -746,73 +847,68 @@ static int rknpu_probe(struct platform_device *pdev) } rknpu_dev->vdd = NULL; } +#endif spin_lock_init(&rknpu_dev->lock); spin_lock_init(&rknpu_dev->irq_lock); - INIT_LIST_HEAD(&rknpu_dev->todo_list); - init_waitqueue_head(&rknpu_dev->job_done_wq); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - LOG_DEV_ERROR(dev, "failed to get memory resource for rknpu\n"); - return -ENXIO; - } - - rknpu_dev->base = devm_ioremap_resource(dev, res); - if (PTR_ERR(rknpu_dev->base) == -EBUSY) { - rknpu_dev->base = - devm_ioremap(dev, res->start, resource_size(res)); - } - - if (IS_ERR(rknpu_dev->base)) { - LOG_DEV_ERROR(dev, "failed to remap register for rknpu\n"); - return PTR_ERR(rknpu_dev->base); - } - - rknpu_dev->bw_priority_base = devm_ioremap( - dev, config->bw_priority_addr, config->bw_priority_length); - if (IS_ERR(rknpu_dev->bw_priority_base)) { - LOG_DEV_ERROR( - rknpu_dev->dev, - "failed to remap bw priority register for rknpu\n"); - rknpu_dev->bw_priority_base = NULL; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - LOG_DEV_ERROR(dev, - "failed to get interrupt resource for rknpu\n"); - return -ENXIO; - } - - if (!rknpu_dev->bypass_irq_handler) { - ret = devm_request_irq(dev, res->start, rknpu_irq_handler, - IRQF_SHARED, dev_name(dev), rknpu_dev); - if (ret) { - LOG_DEV_ERROR(dev, "failed to request irq for rknpu\n"); - return ret; + for (i = 0; i < config->num_irqs; i++) { + INIT_LIST_HEAD(&rknpu_dev->subcore_datas[i].todo_list); + init_waitqueue_head(&rknpu_dev->subcore_datas[i].job_done_wq); + rknpu_dev->subcore_datas[i].task_num = 0; + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) { + LOG_DEV_ERROR( + dev, + "failed to get memory resource for rknpu\n"); + return -ENXIO; + } + + rknpu_dev->base[i] = devm_ioremap_resource(dev, res); + if (PTR_ERR(rknpu_dev->base[i]) == -EBUSY) { + rknpu_dev->base[i] = devm_ioremap(dev, res->start, + resource_size(res)); + } + + if (IS_ERR(rknpu_dev->base[i])) { + LOG_DEV_ERROR(dev, + "failed to remap register for rknpu\n"); + return PTR_ERR(rknpu_dev->base[i]); } - } else { - LOG_DEV_WARN(dev, "bypass irq handler!\n"); } + if (config->bw_priority_length > 0) { + rknpu_dev->bw_priority_base = + devm_ioremap(dev, config->bw_priority_addr, + config->bw_priority_length); + if (IS_ERR(rknpu_dev->bw_priority_base)) { + LOG_DEV_ERROR( + rknpu_dev->dev, + "failed to remap bw priority register for rknpu\n"); + rknpu_dev->bw_priority_base = NULL; + } + } + + if (!rknpu_dev->bypass_irq_handler) + rknpu_register_irq(pdev, rknpu_dev); + ret = rknpu_drm_probe(rknpu_dev); if (ret) { LOG_DEV_ERROR(dev, "failed to probe device for rknpu\n"); return ret; } - rknpu_dev->fence_ctx = rknpu_fence_context_alloc(); - if (IS_ERR(rknpu_dev->fence_ctx)) { + ret = rknpu_fence_context_alloc(rknpu_dev); + if (ret) { LOG_DEV_ERROR(dev, "failed to allocate fence context for rknpu\n"); - ret = PTR_ERR(rknpu_dev->fence_ctx); goto err_remove_drm; } platform_set_drvdata(pdev, rknpu_dev); +#ifndef FPGA_PLATFORM rknpu_devfreq_init(rknpu_dev); +#endif pm_runtime_enable(dev); @@ -832,12 +928,10 @@ static int rknpu_probe(struct platform_device *pdev) ret = rknpu_power_on(rknpu_dev); if (ret) - goto err_free_fence_context; + goto err_remove_drm; return 0; -err_free_fence_context: - rknpu_fence_context_free(rknpu_dev->fence_ctx); err_remove_drm: rknpu_drm_remove(rknpu_dev); @@ -847,14 +941,15 @@ err_remove_drm: static int rknpu_remove(struct platform_device *pdev) { struct rknpu_device *rknpu_dev = platform_get_drvdata(pdev); + int i = 0; - WARN_ON(rknpu_dev->job); - WARN_ON(!list_empty(&rknpu_dev->todo_list)); + for (i = 0; i < rknpu_dev->config->num_irqs; i++) { + WARN_ON(rknpu_dev->subcore_datas[i].job); + WARN_ON(!list_empty(&rknpu_dev->subcore_datas[i].todo_list)); + } rknpu_drm_remove(rknpu_dev); - rknpu_fence_context_free(rknpu_dev->fence_ctx); - rknpu_power_off(rknpu_dev); if (rknpu_dev->multiple_domains) { diff --git a/drivers/rknpu/rknpu_fence.c b/drivers/rknpu/rknpu_fence.c index a03c72521969..529a98ef33ba 100644 --- a/drivers/rknpu/rknpu_fence.c +++ b/drivers/rknpu/rknpu_fence.c @@ -24,24 +24,21 @@ static const struct dma_fence_ops rknpu_fence_ops = { .get_timeline_name = rknpu_fence_get_name, }; -struct rknpu_fence_context *rknpu_fence_context_alloc(void) +int rknpu_fence_context_alloc(struct rknpu_device *rknpu_dev) { struct rknpu_fence_context *fence_ctx = NULL; - fence_ctx = kzalloc(sizeof(*fence_ctx), GFP_KERNEL); + fence_ctx = + devm_kzalloc(rknpu_dev->dev, sizeof(*fence_ctx), GFP_KERNEL); if (!fence_ctx) - return ERR_PTR(-ENOMEM); + return -ENOMEM; fence_ctx->context = dma_fence_context_alloc(1); spin_lock_init(&fence_ctx->spinlock); - return fence_ctx; -} + rknpu_dev->fence_ctx = fence_ctx; -void rknpu_fence_context_free(struct rknpu_fence_context *fence_ctx) -{ - if (!IS_ERR(fence_ctx)) - kfree(fence_ctx); + return 0; } int rknpu_fence_alloc(struct rknpu_job *job) @@ -53,7 +50,7 @@ int rknpu_fence_alloc(struct rknpu_job *job) if (!fence) return -ENOMEM; - dma_fence_init(fence, &rknpu_fence_ops, &job->fence_lock, + dma_fence_init(fence, &rknpu_fence_ops, &fence_ctx->spinlock, fence_ctx->context, ++fence_ctx->seqno); job->fence = fence; diff --git a/drivers/rknpu/rknpu_gem.c b/drivers/rknpu/rknpu_gem.c index fb4ba709c022..15b954ea67d4 100644 --- a/drivers/rknpu/rknpu_gem.c +++ b/drivers/rknpu/rknpu_gem.c @@ -130,9 +130,6 @@ static int rknpu_gem_alloc_buf(struct rknpu_gem_object *rknpu_obj) #endif #ifdef DMA_ATTR_SYS_CACHE_ONLY rknpu_obj->dma_attrs |= DMA_ATTR_SYS_CACHE_ONLY; -#elif DMA_ATTR_FORCE_COHERENT - // force coherent - rknpu_obj->dma_attrs |= DMA_ATTR_FORCE_COHERENT; #endif } else if (rknpu_obj->flags & RKNPU_MEM_WRITE_COMBINE) { rknpu_obj->dma_attrs |= DMA_ATTR_WRITE_COMBINE; @@ -459,7 +456,7 @@ int rknpu_gem_create_ioctl(struct drm_device *dev, void *data, // rknpu_gem_object_get(&rknpu_obj->base); args->size = rknpu_obj->size; - args->obj_addr = (__u64)rknpu_obj; + args->obj_addr = (__u64)(uintptr_t)rknpu_obj; args->dma_addr = rknpu_obj->dma_addr; return 0; @@ -920,7 +917,7 @@ int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data, unsigned long len = 0; int i; - rknpu_obj = (struct rknpu_gem_object *)args->obj_addr; + rknpu_obj = (struct rknpu_gem_object *)(uintptr_t)args->obj_addr; if (!rknpu_obj) return -EINVAL; diff --git a/drivers/rknpu/rknpu_job.c b/drivers/rknpu/rknpu_job.c index 6080035519cd..67a4b9d76734 100644 --- a/drivers/rknpu/rknpu_job.c +++ b/drivers/rknpu/rknpu_job.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include "rknpu_ioctl.h" #include "rknpu_drv.h" @@ -17,8 +19,41 @@ #define _REG_READ(base, offset) readl(base + (offset)) #define _REG_WRITE(base, value, offset) writel(value, base + (offset)) -#define REG_READ(offset) _REG_READ(rknpu_dev->base, offset) -#define REG_WRITE(value, offset) _REG_WRITE(rknpu_dev->base, value, offset) +#define REG_READ(offset) _REG_READ(rknpu_core_base, offset) +#define REG_WRITE(value, offset) _REG_WRITE(rknpu_core_base, value, offset) + +static int rknpu_core_index(int core_mask) +{ + int index = 0; + + if (core_mask & RKNPU_CORE0_MASK) + index = 0; + else if (core_mask & RKNPU_CORE1_MASK) + index = 1; + else if (core_mask & RKNPU_CORE2_MASK) + index = 2; + + return index; +} + +static int rknpu_core_mask(int core_index) +{ + int core_mask[3] = { RKNPU_CORE0_MASK, RKNPU_CORE1_MASK, + RKNPU_CORE2_MASK }; + return core_mask[core_index]; +} + +static int rknn_get_task_number(struct rknpu_job *job, int core_index) +{ + int task_num = job->args->task_number; + + if (job->use_core_num == 2) + task_num = job->args->subcore_task[core_index].task_number; + else if (job->use_core_num == 3) + task_num = job->args->subcore_task[core_index + 2].task_number; + + return task_num; +} static void rknpu_job_free(struct rknpu_job *job) { @@ -27,7 +62,8 @@ static void rknpu_job_free(struct rknpu_job *job) if (job->fence) dma_fence_put(job->fence); - task_obj = (struct rknpu_gem_object *)job->args->task_obj_addr; + task_obj = + (struct rknpu_gem_object *)(uintptr_t)job->args->task_obj_addr; if (task_obj) rknpu_gem_object_put(&task_obj->base); @@ -58,14 +94,22 @@ static inline struct rknpu_job *rknpu_job_alloc(struct rknpu_device *rknpu_dev, struct rknpu_job *job = NULL; struct rknpu_gem_object *task_obj = NULL; + if (rknpu_dev->config->num_irqs == 1) + args->core_mask = RKNPU_CORE0_MASK; + job = kzalloc(sizeof(*job), GFP_KERNEL); if (!job) return NULL; job->timestamp = ktime_get(); job->rknpu_dev = rknpu_dev; + job->use_core_num = (args->core_mask & RKNPU_CORE0_MASK) + + ((args->core_mask & RKNPU_CORE1_MASK) >> 1) + + ((args->core_mask & RKNPU_CORE2_MASK) >> 2); + job->run_count = job->use_core_num; + job->interrupt_count = job->use_core_num; - task_obj = (struct rknpu_gem_object *)args->task_obj_addr; + task_obj = (struct rknpu_gem_object *)(uintptr_t)args->task_obj_addr; if (task_obj) rknpu_gem_object_get(&task_obj->base); @@ -93,9 +137,13 @@ static inline int rknpu_job_wait(struct rknpu_job *job) struct rknpu_device *rknpu_dev = job->rknpu_dev; struct rknpu_submit *args = job->args; struct rknpu_task *last_task = NULL; + struct rknpu_subcore_data *subcore_data = NULL; + void __iomem *rknpu_core_base = NULL; + int core_index = rknpu_core_index(job->args->core_mask); int ret = -EINVAL; - ret = wait_event_interruptible_timeout(rknpu_dev->job_done_wq, + subcore_data = &rknpu_dev->subcore_datas[core_index]; + ret = wait_event_interruptible_timeout(subcore_data->job_done_wq, job->flags & RKNPU_JOB_DONE, msecs_to_jiffies(args->timeout)); @@ -103,10 +151,11 @@ static inline int rknpu_job_wait(struct rknpu_job *job) if (!last_task) return -EINVAL; - last_task->int_status = job->int_status; + last_task->int_status = job->int_status[core_index]; if (ret <= 0) { args->task_counter = 0; + rknpu_core_base = rknpu_dev->base[core_index]; if (args->flags & RKNPU_JOB_PC) { uint32_t task_status = REG_READ(RKNPU_OFFSET_PC_TASK_STATUS); @@ -120,25 +169,48 @@ static inline int rknpu_job_wait(struct rknpu_job *job) return 0; } -static inline int rknpu_job_commit_pc(struct rknpu_job *job) +static inline int rknpu_job_commit_pc(struct rknpu_job *job, int core_index) { struct rknpu_device *rknpu_dev = job->rknpu_dev; struct rknpu_submit *args = job->args; struct rknpu_gem_object *task_obj = - (struct rknpu_gem_object *)args->task_obj_addr; + (struct rknpu_gem_object *)(uintptr_t)args->task_obj_addr; struct rknpu_task *task_base = NULL; struct rknpu_task *first_task = NULL; struct rknpu_task *last_task = NULL; + void __iomem *rknpu_core_base = rknpu_dev->base[core_index]; int task_start = args->task_start; int task_end = args->task_start + args->task_number - 1; + int task_number = args->task_number; int task_pp_en = args->flags & RKNPU_JOB_PINGPONG ? 1 : 0; + int i = 0; + + for (i = 0; i < rknpu_dev->config->num_irqs; i++) { + if (i == core_index) { + REG_WRITE((0xe + 0x10000000 * i), 0x1004); + REG_WRITE((0xe + 0x10000000 * i), 0x3004); + } + } if (!task_obj) return -EINVAL; - if ((task_start + 1) * sizeof(*task_base) > task_obj->size || - (task_end + 1) * sizeof(*task_base) > task_obj->size) - return -EINVAL; + if (job->use_core_num == 1) { + task_start = args->subcore_task[core_index].task_start; + task_end = args->subcore_task[core_index].task_start + + args->subcore_task[core_index].task_end - 1; + task_number = args->subcore_task[core_index].task_number; + } else if (job->use_core_num == 2) { + task_start = args->subcore_task[core_index].task_start; + task_end = args->subcore_task[core_index].task_start + + args->subcore_task[core_index].task_end - 1; + task_number = args->subcore_task[core_index].task_number; + } else if (job->use_core_num == 3) { + task_start = args->subcore_task[core_index + 2].task_start; + task_end = args->subcore_task[core_index + 2].task_start + + args->subcore_task[core_index + 2].task_end - 1; + task_number = args->subcore_task[core_index + 2].task_number; + } task_base = task_obj->kv_addr; @@ -147,21 +219,22 @@ static inline int rknpu_job_commit_pc(struct rknpu_job *job) REG_WRITE(first_task->regcmd_data, RKNPU_OFFSET_PC_DATA_ADDR); - REG_WRITE(first_task->regcfg_amount + RKNPU_PC_DATA_EXTRA_AMOUNT - 1, + REG_WRITE(first_task->regcfg_amount + + rknpu_dev->config->pc_data_extra_amount - 1, RKNPU_OFFSET_PC_DATA_AMOUNT); REG_WRITE(last_task->int_mask, RKNPU_OFFSET_INT_MASK); REG_WRITE(first_task->int_mask, RKNPU_OFFSET_INT_CLEAR); - REG_WRITE(((0x6 | task_pp_en) << 12) | args->task_number, + REG_WRITE(((0x6 | task_pp_en) << 12) | task_number, RKNPU_OFFSET_PC_TASK_CONTROL); REG_WRITE(0x0, RKNPU_OFFSET_PC_DMA_BASE_ADDR); job->first_task = first_task; job->last_task = last_task; - job->int_mask = last_task->int_mask; + job->int_mask[core_index] = last_task->int_mask; REG_WRITE(0x1, RKNPU_OFFSET_PC_OP_EN); REG_WRITE(0x0, RKNPU_OFFSET_PC_OP_EN); @@ -169,10 +242,11 @@ static inline int rknpu_job_commit_pc(struct rknpu_job *job) return 0; } -static int rknpu_job_commit(struct rknpu_job *job) +static int rknpu_job_commit(struct rknpu_job *job, int core_index) { struct rknpu_device *rknpu_dev = job->rknpu_dev; struct rknpu_submit *args = job->args; + void __iomem *rknpu_core_base = rknpu_dev->base[core_index]; // switch to slave mode REG_WRITE(0x1, RKNPU_OFFSET_PC_DATA_ADDR); @@ -180,49 +254,73 @@ static int rknpu_job_commit(struct rknpu_job *job) if (!(args->flags & RKNPU_JOB_PC)) return -EINVAL; - return rknpu_job_commit_pc(job); + return rknpu_job_commit_pc(job, core_index); } -static void rknpu_job_next(struct rknpu_device *rknpu_dev) +static void rknpu_job_next(struct rknpu_device *rknpu_dev, int core_index) { struct rknpu_job *job = NULL; + struct rknpu_subcore_data *subcore_data = NULL; unsigned long flags; + subcore_data = &rknpu_dev->subcore_datas[core_index]; + spin_lock_irqsave(&rknpu_dev->irq_lock, flags); - if (rknpu_dev->job || list_empty(&rknpu_dev->todo_list)) { + if (subcore_data->job || list_empty(&subcore_data->todo_list)) { spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags); return; } - job = list_first_entry(&rknpu_dev->todo_list, struct rknpu_job, head); + job = list_first_entry(&subcore_data->todo_list, struct rknpu_job, + head[core_index]); - list_del_init(&job->head); + list_del_init(&job->head[core_index]); - rknpu_dev->job = job; + subcore_data->job = job; + job->run_count--; spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags); - job->ret = rknpu_job_commit(job); + if (job->run_count == 0) { + if (job->args->core_mask & RKNPU_CORE0_MASK) + job->ret = rknpu_job_commit(job, 0); + if (job->args->core_mask & RKNPU_CORE1_MASK) + job->ret = rknpu_job_commit(job, 1); + if (job->args->core_mask & RKNPU_CORE2_MASK) + job->ret = rknpu_job_commit(job, 2); + } } -static void rknpu_job_done(struct rknpu_job *job, int ret) +static void rknpu_job_done(struct rknpu_job *job, int ret, int core_index) { struct rknpu_device *rknpu_dev = job->rknpu_dev; + struct rknpu_subcore_data *subcore_data = NULL; unsigned long flags; + int task_num = 0; + subcore_data = &rknpu_dev->subcore_datas[core_index]; + task_num = rknn_get_task_number(job, core_index); spin_lock_irqsave(&rknpu_dev->irq_lock, flags); - rknpu_dev->job = NULL; + subcore_data->job = NULL; + subcore_data->task_num = subcore_data->task_num - task_num; + job->interrupt_count--; spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags); - job->flags |= RKNPU_JOB_DONE; - job->ret = ret; + if (job->interrupt_count == 0) { + job->flags |= RKNPU_JOB_DONE; + job->ret = ret; - if (job->fence) - dma_fence_signal(job->fence); + if (job->fence) + dma_fence_signal(job->fence); - wake_up(&rknpu_dev->job_done_wq); - rknpu_job_next(rknpu_dev); + if (job->use_core_num > 1) + wake_up(&(&rknpu_dev->subcore_datas[0])->job_done_wq); + else + wake_up(&subcore_data->job_done_wq); + } + + rknpu_job_next(rknpu_dev, core_index); if (job->flags & RKNPU_JOB_ASYNC) schedule_work(&job->cleanup_work); @@ -231,28 +329,97 @@ static void rknpu_job_done(struct rknpu_job *job, int ret) static void rknpu_job_schedule(struct rknpu_job *job) { struct rknpu_device *rknpu_dev = job->rknpu_dev; + struct rknpu_subcore_data *subcore_data = NULL; + int i = 0, core_index = 0; unsigned long flags; + int task_num_list[3] = { 0, 1, 2 }; + int task_num = 0; + int tmp = 0; + + if ((job->args->core_mask & 0x07) == RKNPU_CORE_AUTO_MASK) { + if (rknpu_dev->subcore_datas[0].task_num > + rknpu_dev->subcore_datas[1].task_num) { + tmp = task_num_list[1]; + task_num_list[1] = task_num_list[0]; + task_num_list[0] = tmp; + } + if (rknpu_dev->subcore_datas[task_num_list[0]].task_num > + rknpu_dev->subcore_datas[2].task_num) { + tmp = task_num_list[2]; + task_num_list[2] = task_num_list[1]; + task_num_list[1] = task_num_list[0]; + task_num_list[0] = tmp; + } else if (rknpu_dev->subcore_datas[task_num_list[1]].task_num > + rknpu_dev->subcore_datas[2].task_num) { + tmp = task_num_list[2]; + task_num_list[2] = task_num_list[1]; + task_num_list[1] = tmp; + } + if (!rknpu_dev->subcore_datas[task_num_list[0]].job) + core_index = task_num_list[0]; + else if (!rknpu_dev->subcore_datas[task_num_list[1]].job) + core_index = task_num_list[1]; + else if (!rknpu_dev->subcore_datas[task_num_list[2]].job) + core_index = task_num_list[2]; + else + core_index = task_num_list[0]; + + job->args->core_mask = rknpu_core_mask(core_index); + job->use_core_num = 1; + job->interrupt_count = 1; + job->run_count = 1; + } spin_lock_irqsave(&rknpu_dev->irq_lock, flags); - list_add_tail(&job->head, &rknpu_dev->todo_list); + for (i = 0; i < rknpu_dev->config->num_irqs; i++) { + if (job->args->core_mask & rknpu_core_mask(i)) { + subcore_data = &rknpu_dev->subcore_datas[i]; + task_num = rknn_get_task_number(job, i); + subcore_data->task_num = + subcore_data->task_num + task_num; + list_add_tail(&job->head[i], &subcore_data->todo_list); + } + } spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags); - rknpu_job_next(rknpu_dev); + for (i = 0; i < rknpu_dev->config->num_irqs; i++) { + if (job->args->core_mask & rknpu_core_mask(i)) + rknpu_job_next(rknpu_dev, i); + } } static void rknpu_job_abort(struct rknpu_job *job) { struct rknpu_device *rknpu_dev = job->rknpu_dev; + struct rknpu_subcore_data *subcore_data = NULL; + int core_index = rknpu_core_index(job->args->core_mask); + void __iomem *rknpu_core_base = rknpu_dev->base[core_index]; unsigned long flags; + int i = 0; + int task_num = 0; msleep(100); - if (job->ret == -ETIMEDOUT) + if (job->ret == -ETIMEDOUT) { + LOG_ERROR( + "job timeout, irq status: %#x, raw status: %#x, require mask: %#x\n", + REG_READ(RKNPU_OFFSET_INT_STATUS), + REG_READ(RKNPU_OFFSET_INT_RAW_STATUS), + job->int_mask[core_index]); rknpu_soft_reset(rknpu_dev); - - if (job == rknpu_dev->job) { - spin_lock_irqsave(&rknpu_dev->irq_lock, flags); - rknpu_dev->job = NULL; - spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags); + } + for (i = 0; i < rknpu_dev->config->num_irqs; i++) { + if (job->args->core_mask & rknpu_core_mask(i)) { + subcore_data = &rknpu_dev->subcore_datas[i]; + if (job == subcore_data->job) { + spin_lock_irqsave(&rknpu_dev->irq_lock, flags); + task_num = rknn_get_task_number(job, i); + subcore_data->job = NULL; + subcore_data->task_num = + subcore_data->task_num - task_num; + spin_unlock_irqrestore(&rknpu_dev->irq_lock, + flags); + } + } } rknpu_job_cleanup(job); @@ -283,10 +450,11 @@ static inline uint32_t rknpu_fuzz_status(uint32_t status) return fuzz_status; } -irqreturn_t rknpu_irq_handler(int irq, void *data) +static inline irqreturn_t rknpu_irq_handler(int irq, void *data, int core_index) { struct rknpu_device *rknpu_dev = data; - struct rknpu_job *job = rknpu_dev->job; + struct rknpu_job *job = rknpu_dev->subcore_datas[core_index].job; + void __iomem *rknpu_core_base = rknpu_dev->base[core_index]; uint32_t status = 0; if (!job) @@ -295,49 +463,81 @@ irqreturn_t rknpu_irq_handler(int irq, void *data) status = REG_READ(RKNPU_OFFSET_INT_STATUS); REG_WRITE(RKNPU_INT_CLEAR, RKNPU_OFFSET_INT_CLEAR); - job->int_status = status; + job->int_status[core_index] = status; - if (rknpu_fuzz_status(status) != job->int_mask) { - LOG_DEBUG("irq: status = %#x, mask = %#x\n", status, - job->int_mask); + if (rknpu_fuzz_status(status) != job->int_mask[core_index]) { + LOG_ERROR( + "invalid irq status: %#x, raw status: %#x, require mask: %#x\n", + status, REG_READ(RKNPU_OFFSET_INT_RAW_STATUS), + job->int_mask[core_index]); return IRQ_HANDLED; } - rknpu_job_done(job, 0); + rknpu_job_done(job, 0, core_index); return IRQ_HANDLED; } -static void rknpu_job_timeout_clean(struct rknpu_device *rknpu_dev) +irqreturn_t rknpu_core0_irq_handler(int irq, void *data) +{ + return rknpu_irq_handler(irq, data, 0); +} + +irqreturn_t rknpu_core1_irq_handler(int irq, void *data) +{ + return rknpu_irq_handler(irq, data, 1); +} + +irqreturn_t rknpu_core2_irq_handler(int irq, void *data) +{ + return rknpu_irq_handler(irq, data, 2); +} + +static void rknpu_job_timeout_clean(struct rknpu_device *rknpu_dev, + int core_mask) { struct rknpu_job *job = NULL; unsigned long flags; ktime_t now = ktime_get(); + struct rknpu_subcore_data *subcore_data = NULL; + int i = 0; - job = rknpu_dev->job; - if (job && - ktime_to_ms(ktime_sub(now, job->timestamp)) >= job->args->timeout) { - rknpu_soft_reset(rknpu_dev); + for (i = 0; i < rknpu_dev->config->num_irqs; i++) { + if (core_mask & rknpu_core_mask(i)) { + subcore_data = &rknpu_dev->subcore_datas[i]; + job = subcore_data->job; + if (job && + ktime_to_ms(ktime_sub(now, job->timestamp)) >= + job->args->timeout) { + rknpu_soft_reset(rknpu_dev); - spin_lock_irqsave(&rknpu_dev->irq_lock, flags); - rknpu_dev->job = NULL; - spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags); + spin_lock_irqsave(&rknpu_dev->irq_lock, flags); + subcore_data->job = NULL; + spin_unlock_irqrestore(&rknpu_dev->irq_lock, + flags); - do { - schedule_work(&job->cleanup_work); + do { + schedule_work(&job->cleanup_work); - spin_lock_irqsave(&rknpu_dev->irq_lock, flags); + spin_lock_irqsave(&rknpu_dev->irq_lock, + flags); - if (!list_empty(&rknpu_dev->todo_list)) { - job = list_first_entry(&rknpu_dev->todo_list, - struct rknpu_job, head); - list_del_init(&job->head); - } else { - job = NULL; + if (!list_empty( + &subcore_data->todo_list)) { + job = list_first_entry( + &subcore_data->todo_list, + struct rknpu_job, + head[i]); + list_del_init(&job->head[i]); + } else { + job = NULL; + } + + spin_unlock_irqrestore( + &rknpu_dev->irq_lock, flags); + } while (job); } - - spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags); - } while (job); + } } } @@ -360,7 +560,38 @@ int rknpu_submit_ioctl(struct drm_device *dev, void *data, return -ENOMEM; } - if (args->flags & RKNPU_JOB_FENCE) { + if (args->flags & RKNPU_JOB_FENCE_IN) { + struct dma_fence *in_fence; + + in_fence = sync_file_get_fence(args->fence_fd); + + if (!in_fence) { + LOG_ERROR("invalid fence in fd, fd = %d\n", + args->fence_fd); + return -EINVAL; + } + args->fence_fd = -1; + + /* + * Wait if the fence is from a foreign context, or if the fence + * array contains any fence from a foreign context. + */ + ret = 0; + if (!dma_fence_match_context(in_fence, + rknpu_dev->fence_ctx->context)) + ret = dma_fence_wait_timeout(in_fence, true, + args->timeout); + dma_fence_put(in_fence); + if (ret < 0) { + if (ret != -ERESTARTSYS) + LOG_ERROR("Error (%d) waiting for fence!\n", + ret); + + return ret; + } + } + + if (args->flags & RKNPU_JOB_FENCE_OUT) { ret = rknpu_fence_alloc(job); if (ret) { rknpu_job_free(job); @@ -372,7 +603,7 @@ int rknpu_submit_ioctl(struct drm_device *dev, void *data, if (args->flags & RKNPU_JOB_NONBLOCK) { job->flags |= RKNPU_JOB_ASYNC; - rknpu_job_timeout_clean(rknpu_dev); + rknpu_job_timeout_clean(rknpu_dev, job->args->core_mask); rknpu_job_schedule(job); ret = job->ret; if (ret) { @@ -397,6 +628,8 @@ int rknpu_submit_ioctl(struct drm_device *dev, void *data, int rknpu_get_hw_version(struct rknpu_device *rknpu_dev, uint32_t *version) { + void __iomem *rknpu_core_base = rknpu_dev->base[0]; + if (version != NULL) *version = REG_READ(RKNPU_OFFSET_VERSION); @@ -408,6 +641,11 @@ int rknpu_get_bw_priority(struct rknpu_device *rknpu_dev, uint32_t *priority, { void __iomem *base = rknpu_dev->bw_priority_base; + if (!rknpu_dev->config->bw_enable) { + LOG_WARN("Get bw_priority is not supported on this device!\n"); + return 0; + } + if (!base) return -EINVAL; @@ -432,6 +670,11 @@ int rknpu_set_bw_priority(struct rknpu_device *rknpu_dev, uint32_t priority, { void __iomem *base = rknpu_dev->bw_priority_base; + if (!rknpu_dev->config->bw_enable) { + LOG_WARN("Set bw_priority is not supported on this device!\n"); + return 0; + } + if (!base) return -EINVAL; @@ -453,6 +696,13 @@ int rknpu_set_bw_priority(struct rknpu_device *rknpu_dev, uint32_t priority, int rknpu_clear_rw_amount(struct rknpu_device *rknpu_dev) { + void __iomem *rknpu_core_base = rknpu_dev->base[0]; + + if (!rknpu_dev->config->bw_enable) { + LOG_WARN("Clear rw_amount is not supported on this device!\n"); + return 0; + } + spin_lock(&rknpu_dev->lock); REG_WRITE(0x80000101, RKNPU_OFFSET_CLR_ALL_RW_AMOUNT); @@ -466,6 +716,13 @@ int rknpu_clear_rw_amount(struct rknpu_device *rknpu_dev) int rknpu_get_rw_amount(struct rknpu_device *rknpu_dev, uint32_t *dt_wr, uint32_t *dt_rd, uint32_t *wd_rd) { + void __iomem *rknpu_core_base = rknpu_dev->base[0]; + + if (!rknpu_dev->config->bw_enable) { + LOG_WARN("Get rw_amount is not supported on this device!\n"); + return 0; + } + spin_lock(&rknpu_dev->lock); if (dt_wr != NULL) @@ -489,6 +746,12 @@ int rknpu_get_total_rw_amount(struct rknpu_device *rknpu_dev, uint32_t *amount) uint32_t wd_rd = 0; int ret = -EINVAL; + if (!rknpu_dev->config->bw_enable) { + LOG_WARN( + "Get total_rw_amount is not supported on this device!\n"); + return 0; + } + ret = rknpu_get_rw_amount(rknpu_dev, &dt_wr, &dt_rd, &wd_rd); if (amount != NULL) diff --git a/drivers/rknpu/rknpu_reset.c b/drivers/rknpu/rknpu_reset.c index 1b0f77df9d87..681647afd964 100644 --- a/drivers/rknpu/rknpu_reset.c +++ b/drivers/rknpu/rknpu_reset.c @@ -9,6 +9,7 @@ #include "rknpu_reset.h" +#ifndef FPGA_PLATFORM static inline struct reset_control *rknpu_reset_control_get(struct device *dev, const char *name) { @@ -22,27 +23,38 @@ static inline struct reset_control *rknpu_reset_control_get(struct device *dev, return rst; } +#endif int rknpu_reset_get(struct rknpu_device *rknpu_dev) { +#ifndef FPGA_PLATFORM struct reset_control *srst_a = NULL; struct reset_control *srst_h = NULL; + int i = 0; - srst_a = rknpu_reset_control_get(rknpu_dev->dev, "srst_a"); - if (IS_ERR(srst_a)) - return PTR_ERR(srst_a); + for (i = 0; i < rknpu_dev->config->num_resets; i++) { + srst_a = rknpu_reset_control_get( + rknpu_dev->dev, + rknpu_dev->config->resets[i].srst_a_name); + if (IS_ERR(srst_a)) + return PTR_ERR(srst_a); - rknpu_dev->srst_a = srst_a; + rknpu_dev->srst_a[i] = srst_a; - srst_h = devm_reset_control_get(rknpu_dev->dev, "srst_h"); - if (IS_ERR(srst_h)) - return PTR_ERR(srst_h); + srst_h = rknpu_reset_control_get( + rknpu_dev->dev, + rknpu_dev->config->resets[i].srst_h_name); + if (IS_ERR(srst_h)) + return PTR_ERR(srst_h); - rknpu_dev->srst_h = srst_h; + rknpu_dev->srst_h[i] = srst_h; + } +#endif return 0; } +#ifndef FPGA_PLATFORM static int rknpu_reset_assert(struct reset_control *rst) { int ret = -EINVAL; @@ -74,11 +86,13 @@ static int rknpu_reset_deassert(struct reset_control *rst) return 0; } +#endif int rknpu_soft_reset(struct rknpu_device *rknpu_dev) { +#ifndef FPGA_PLATFORM struct iommu_domain *domain = NULL; - int ret = -EINVAL; + int ret = -EINVAL, i = 0; if (rknpu_dev->bypass_soft_reset) { LOG_WARN("bypass soft reset\n"); @@ -87,13 +101,15 @@ int rknpu_soft_reset(struct rknpu_device *rknpu_dev) LOG_INFO("soft reset\n"); - ret = rknpu_reset_assert(rknpu_dev->srst_a); - ret |= rknpu_reset_assert(rknpu_dev->srst_h); + for (i = 0; i < rknpu_dev->config->num_resets; i++) { + ret = rknpu_reset_assert(rknpu_dev->srst_a[i]); + ret |= rknpu_reset_assert(rknpu_dev->srst_h[i]); - udelay(10); + udelay(10); - ret |= rknpu_reset_deassert(rknpu_dev->srst_a); - ret |= rknpu_reset_deassert(rknpu_dev->srst_h); + ret |= rknpu_reset_deassert(rknpu_dev->srst_a[i]); + ret |= rknpu_reset_deassert(rknpu_dev->srst_h[i]); + } if (ret) { LOG_DEV_ERROR(rknpu_dev->dev, @@ -108,6 +124,7 @@ int rknpu_soft_reset(struct rknpu_device *rknpu_dev) iommu_detach_device(domain, rknpu_dev->dev); iommu_attach_device(domain, rknpu_dev->dev); } +#endif - return ret; + return 0; }