mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
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:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user