driver: rknpu: Update rknpu driver, version: 0.9.4

Signed-off-by: Felix Zeng <felix.zeng@rock-chips.com>
Change-Id: Ibeaacee69a264b716e636c6397aa9a49068bd8cf
This commit is contained in:
Felix Zeng
2024-01-30 15:05:12 +08:00
committed by Tao Huang
parent caeb85ae6f
commit 4a35fccb35
5 changed files with 127 additions and 49 deletions

View File

@@ -10,6 +10,7 @@
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/kref.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/regulator/consumer.h>
@@ -28,10 +29,10 @@
#define DRIVER_NAME "rknpu"
#define DRIVER_DESC "RKNPU driver"
#define DRIVER_DATE "20231121"
#define DRIVER_DATE "20240129"
#define DRIVER_MAJOR 0
#define DRIVER_MINOR 9
#define DRIVER_PATCHLEVEL 3
#define DRIVER_PATCHLEVEL 4
#define LOG_TAG "RKNPU"
@@ -52,11 +53,23 @@
#define LOG_DEV_DEBUG(dev, fmt, args...) dev_dbg(dev, LOG_TAG ": " fmt, ##args)
#define LOG_DEV_ERROR(dev, fmt, args...) dev_err(dev, LOG_TAG ": " fmt, ##args)
struct rknpu_irqs_data {
const char *name;
irqreturn_t (*irq_hdl)(int irq, void *ctx);
};
struct rknpu_reset_data {
const char *srst_a_name;
const char *srst_h_name;
};
struct rknpu_amount_data {
uint16_t offset_clr_all;
uint16_t offset_dt_wr;
uint16_t offset_dt_rd;
uint16_t offset_wt_rd;
};
struct rknpu_config {
__u32 bw_priority_addr;
__u32 bw_priority_length;
@@ -66,7 +79,6 @@ struct rknpu_config {
__u32 pc_task_number_mask;
__u32 pc_task_status_offset;
__u32 pc_dma_ctrl;
__u32 bw_enable;
const struct rknpu_irqs_data *irqs;
const struct rknpu_reset_data *resets;
int num_irqs;
@@ -75,6 +87,8 @@ struct rknpu_config {
__u64 nbuf_size;
__u64 max_submit_number;
__u32 core_mask;
const struct rknpu_amount_data *amount_top;
const struct rknpu_amount_data *amount_core;
};
struct rknpu_timer {

View File

@@ -31,11 +31,6 @@
#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
#define RKNPU_OFFSET_DT_RD_AMOUNT 0x8038
#define RKNPU_OFFSET_WT_RD_AMOUNT 0x803c
#define RKNPU_OFFSET_ENABLE_MASK 0xf008
#define RKNPU_INT_CLEAR 0x1ffff

View File

@@ -8,7 +8,6 @@
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/iopoll.h>
#include <linux/module.h>
@@ -72,11 +71,6 @@ 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 rknpu_irqs_data {
const char *name;
irqreturn_t (*irq_hdl)(int irq, void *ctx);
};
static const struct rknpu_irqs_data rknpu_irqs[] = {
{ "npu_irq", rknpu_core0_irq_handler }
};
@@ -96,6 +90,27 @@ static const struct rknpu_reset_data rk3588_npu_resets[] = {
{ "srst_a2", "srst_h2" }
};
static const struct rknpu_amount_data rknpu_old_top_amount = {
.offset_clr_all = 0x8010,
.offset_dt_wr = 0x8034,
.offset_dt_rd = 0x8038,
.offset_wt_rd = 0x803c,
};
static const struct rknpu_amount_data rknpu_top_amount = {
.offset_clr_all = 0x2210,
.offset_dt_wr = 0x2234,
.offset_dt_rd = 0x2238,
.offset_wt_rd = 0x223c
};
static const struct rknpu_amount_data rknpu_core_amount = {
.offset_clr_all = 0x2410,
.offset_dt_wr = 0x2434,
.offset_dt_rd = 0x2438,
.offset_wt_rd = 0x243c,
};
static const struct rknpu_config rk356x_rknpu_config = {
.bw_priority_addr = 0xfe180008,
.bw_priority_length = 0x10,
@@ -105,7 +120,6 @@ static const struct rknpu_config rk356x_rknpu_config = {
.pc_task_number_mask = 0xfff,
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.bw_enable = 1,
.irqs = rknpu_irqs,
.resets = rknpu_resets,
.num_irqs = ARRAY_SIZE(rknpu_irqs),
@@ -114,6 +128,8 @@ static const struct rknpu_config rk356x_rknpu_config = {
.nbuf_size = 0,
.max_submit_number = (1 << 12) - 1,
.core_mask = 0x1,
.amount_top = &rknpu_old_top_amount,
.amount_core = NULL,
};
static const struct rknpu_config rk3588_rknpu_config = {
@@ -125,7 +141,6 @@ static const struct rknpu_config rk3588_rknpu_config = {
.pc_task_number_mask = 0xfff,
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.bw_enable = 0,
.irqs = rk3588_npu_irqs,
.resets = rk3588_npu_resets,
.num_irqs = ARRAY_SIZE(rk3588_npu_irqs),
@@ -134,6 +149,8 @@ static const struct rknpu_config rk3588_rknpu_config = {
.nbuf_size = 0,
.max_submit_number = (1 << 12) - 1,
.core_mask = 0x7,
.amount_top = NULL,
.amount_core = NULL,
};
static const struct rknpu_config rk3583_rknpu_config = {
@@ -145,7 +162,6 @@ static const struct rknpu_config rk3583_rknpu_config = {
.pc_task_number_mask = 0xfff,
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.bw_enable = 0,
.irqs = rk3588_npu_irqs,
.resets = rk3588_npu_resets,
.num_irqs = 2,
@@ -154,6 +170,8 @@ static const struct rknpu_config rk3583_rknpu_config = {
.nbuf_size = 0,
.max_submit_number = (1 << 12) - 1,
.core_mask = 0x3,
.amount_top = NULL,
.amount_core = NULL,
};
static const struct rknpu_config rv1106_rknpu_config = {
@@ -165,7 +183,6 @@ static const struct rknpu_config rv1106_rknpu_config = {
.pc_task_number_mask = 0xffff,
.pc_task_status_offset = 0x3c,
.pc_dma_ctrl = 0,
.bw_enable = 1,
.irqs = rknpu_irqs,
.resets = rknpu_resets,
.num_irqs = ARRAY_SIZE(rknpu_irqs),
@@ -174,6 +191,8 @@ static const struct rknpu_config rv1106_rknpu_config = {
.nbuf_size = 0,
.max_submit_number = (1 << 16) - 1,
.core_mask = 0x1,
.amount_top = &rknpu_old_top_amount,
.amount_core = NULL,
};
static const struct rknpu_config rk3562_rknpu_config = {
@@ -185,7 +204,6 @@ static const struct rknpu_config rk3562_rknpu_config = {
.pc_task_number_mask = 0xffff,
.pc_task_status_offset = 0x48,
.pc_dma_ctrl = 1,
.bw_enable = 1,
.irqs = rknpu_irqs,
.resets = rknpu_resets,
.num_irqs = ARRAY_SIZE(rknpu_irqs),
@@ -194,6 +212,8 @@ static const struct rknpu_config rk3562_rknpu_config = {
.nbuf_size = 256 * 1024,
.max_submit_number = (1 << 16) - 1,
.core_mask = 0x1,
.amount_top = &rknpu_old_top_amount,
.amount_core = NULL,
};
/* driver probe and init */
@@ -952,9 +972,12 @@ static int rknpu_register_irq(struct platform_device *pdev,
{
const struct rknpu_config *config = rknpu_dev->config;
struct device *dev = &pdev->dev;
#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
struct resource *res;
#endif
int i, ret, irq;
#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
config->irqs[0].name);
if (res) {
@@ -993,6 +1016,28 @@ static int rknpu_register_irq(struct platform_device *pdev,
return ret;
}
}
#else
/* 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) {
irq = platform_get_irq(pdev, i);
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;
}
}
#endif
return 0;
}

View File

@@ -15,6 +15,7 @@
#include <linux/iommu.h>
#include <linux/pfn_t.h>
#include <linux/version.h>
#include <linux/version_compat_defs.h>
#include <asm/cacheflush.h>
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
@@ -889,7 +890,7 @@ static int rknpu_gem_mmap_pages(struct rknpu_gem_object *rknpu_obj,
struct drm_device *drm = rknpu_obj->base.dev;
int ret = -EINVAL;
vma->vm_flags |= VM_MIXEDMAP;
vm_flags_set(vma, VM_MIXEDMAP);
ret = __vm_map_pages(vma, rknpu_obj->pages, rknpu_obj->num_pages,
vma->vm_pgoff);
@@ -935,7 +936,7 @@ static int rknpu_gem_mmap_cache(struct rknpu_gem_object *rknpu_obj,
return -EINVAL;
}
vma->vm_flags |= VM_MIXEDMAP;
vm_flags_set(vma, VM_MIXEDMAP);
vm_size = vma->vm_end - vma->vm_start;
@@ -985,8 +986,8 @@ static int rknpu_gem_mmap_buffer(struct rknpu_gem_object *rknpu_obj,
* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
* the whole buffer.
*/
vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
vma->vm_flags &= ~VM_PFNMAP;
vm_flags_set(vma, VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO);
vm_flags_clear(vma, VM_PFNMAP);
vma->vm_pgoff = 0;
vm_size = vma->vm_end - vma->vm_start;
@@ -1336,7 +1337,7 @@ int rknpu_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
return -EINVAL;
vaddr = vmap(rknpu_obj->pages, rknpu_obj->num_pages, VM_MAP,
PAGE_KERNEL);
PAGE_KERNEL);
if (!vaddr)
return -ENOMEM;

View File

@@ -885,11 +885,6 @@ 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;
@@ -914,11 +909,6 @@ 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;
@@ -941,28 +931,41 @@ 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];
const struct rknpu_config *config = rknpu_dev->config;
unsigned long flags;
if (!rknpu_dev->config->bw_enable) {
if (config->amount_top == NULL) {
LOG_WARN("Clear rw_amount is not supported on this device!\n");
return 0;
}
if (rknpu_dev->config->pc_dma_ctrl) {
if (config->pc_dma_ctrl) {
uint32_t pc_data_addr = 0;
spin_lock_irqsave(&rknpu_dev->irq_lock, flags);
pc_data_addr = REG_READ(RKNPU_OFFSET_PC_DATA_ADDR);
REG_WRITE(0x1, RKNPU_OFFSET_PC_DATA_ADDR);
REG_WRITE(0x80000101, RKNPU_OFFSET_CLR_ALL_RW_AMOUNT);
REG_WRITE(0x00000101, RKNPU_OFFSET_CLR_ALL_RW_AMOUNT);
REG_WRITE(0x80000101, config->amount_top->offset_clr_all);
REG_WRITE(0x00000101, config->amount_top->offset_clr_all);
if (config->amount_core) {
REG_WRITE(0x80000101,
config->amount_core->offset_clr_all);
REG_WRITE(0x00000101,
config->amount_core->offset_clr_all);
}
REG_WRITE(pc_data_addr, RKNPU_OFFSET_PC_DATA_ADDR);
spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags);
} else {
spin_lock(&rknpu_dev->lock);
REG_WRITE(0x80000101, RKNPU_OFFSET_CLR_ALL_RW_AMOUNT);
REG_WRITE(0x00000101, RKNPU_OFFSET_CLR_ALL_RW_AMOUNT);
REG_WRITE(0x80000101, config->amount_top->offset_clr_all);
REG_WRITE(0x00000101, config->amount_top->offset_clr_all);
if (config->amount_core) {
REG_WRITE(0x80000101,
config->amount_core->offset_clr_all);
REG_WRITE(0x00000101,
config->amount_core->offset_clr_all);
}
spin_unlock(&rknpu_dev->lock);
}
@@ -973,23 +976,42 @@ 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];
int amount_scale = rknpu_dev->config->pc_data_amount_scale;
const struct rknpu_config *config = rknpu_dev->config;
int amount_scale = config->pc_data_amount_scale;
if (!rknpu_dev->config->bw_enable) {
if (config->amount_top == NULL) {
LOG_WARN("Get rw_amount is not supported on this device!\n");
return 0;
}
spin_lock(&rknpu_dev->lock);
if (dt_wr != NULL)
*dt_wr = REG_READ(RKNPU_OFFSET_DT_WR_AMOUNT) * amount_scale;
if (dt_wr != NULL) {
*dt_wr = REG_READ(config->amount_top->offset_dt_wr) *
amount_scale;
if (config->amount_core) {
*dt_wr += REG_READ(config->amount_core->offset_dt_wr) *
amount_scale;
}
}
if (dt_rd != NULL)
*dt_rd = REG_READ(RKNPU_OFFSET_DT_RD_AMOUNT) * amount_scale;
if (dt_rd != NULL) {
*dt_rd = REG_READ(config->amount_top->offset_dt_rd) *
amount_scale;
if (config->amount_core) {
*dt_rd += REG_READ(config->amount_core->offset_dt_rd) *
amount_scale;
}
}
if (wd_rd != NULL)
*wd_rd = REG_READ(RKNPU_OFFSET_WT_RD_AMOUNT) * amount_scale;
if (wd_rd != NULL) {
*wd_rd = REG_READ(config->amount_top->offset_wt_rd) *
amount_scale;
if (config->amount_core) {
*wd_rd += REG_READ(config->amount_core->offset_wt_rd) *
amount_scale;
}
}
spin_unlock(&rknpu_dev->lock);
@@ -998,12 +1020,13 @@ int rknpu_get_rw_amount(struct rknpu_device *rknpu_dev, uint32_t *dt_wr,
int rknpu_get_total_rw_amount(struct rknpu_device *rknpu_dev, uint32_t *amount)
{
const struct rknpu_config *config = rknpu_dev->config;
uint32_t dt_wr = 0;
uint32_t dt_rd = 0;
uint32_t wd_rd = 0;
int ret = -EINVAL;
if (!rknpu_dev->config->bw_enable) {
if (config->amount_top == NULL) {
LOG_WARN(
"Get total_rw_amount is not supported on this device!\n");
return 0;