###### 本文件主要记录在移植3588 NPU 0.9.8版本的过程中,遇到的问题以及解决办法 ######
1.下载NPU 0.9.8版本NPU
rknpu-driver/rknpu_driver_0.9.8_20241009.tar.bz2 · 虾米/rknn-llm - 码云 - 开源中国
2.替换旧版本NPU驱动
将rknpu_driver_0.9.8_20241009/drivers/rknpu 拷贝到 3588/OK3588_Linux_fs/kernel/drivers/rknpu 下
3.编译遇到的问题
3.1 错误信息如下:
./include/soc/rockchip/rockchip_system_monitor.h:90:26: error: field 'max_temp_freq_req' has incomplete type
90 | struct freq_qos_request max_temp_freq_req;
解决办法:在rockchip_system_monitor.h下添加以下内容
#include <linux/pm_opp.h>
#include <linux/pm_qos.h>
#include <linux/regulator/consumer.h>
3.2 错误信息如下:
drivers/rknpu/rknpu_gem.c:18:10: fatal error: linux/version_compat_defs.h: No such file or directory
18 | #include <linux/version_compat_defs.h>
解决办法:在include/linux下创建version_compat_defs.h,内容如下:
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2022-2023 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#ifndef _VERSION_COMPAT_DEFS_H_
#define _VERSION_COMPAT_DEFS_H_
#include <linux/version.h>
#if KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE
typedef unsigned int __poll_t;
#endif
#if KERNEL_VERSION(4, 9, 78) >= LINUX_VERSION_CODE
#ifndef EPOLLHUP
#define EPOLLHUP POLLHUP
#endif
#ifndef EPOLLERR
#define EPOLLERR POLLERR
#endif
#ifndef EPOLLIN
#define EPOLLIN POLLIN
#endif
#ifndef EPOLLRDNORM
#define EPOLLRDNORM POLLRDNORM
#endif
#endif
#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
/* This is defined inside kbase for matching the default to kernel's
* mmap_min_addr, used inside file mali_kbase_mmap.c.
* Note: the value is set at compile time, matching a kernel's configuration
* value. It would not be able to track any runtime update of mmap_min_addr.
*/
#ifdef CONFIG_MMU
#define kbase_mmap_min_addr CONFIG_DEFAULT_MMAP_MIN_ADDR
#ifdef CONFIG_LSM_MMAP_MIN_ADDR
#if (CONFIG_LSM_MMAP_MIN_ADDR > CONFIG_DEFAULT_MMAP_MIN_ADDR)
/* Replace the default definition with CONFIG_LSM_MMAP_MIN_ADDR */
#undef kbase_mmap_min_addr
#define kbase_mmap_min_addr CONFIG_LSM_MMAP_MIN_ADDR
#pragma message "kbase_mmap_min_addr compiled to CONFIG_LSM_MMAP_MIN_ADDR, no runtime update!"
#endif /* (CONFIG_LSM_MMAP_MIN_ADDR > CONFIG_DEFAULT_MMAP_MIN_ADDR) */
#endif /* CONFIG_LSM_MMAP_MIN_ADDR */
#if (kbase_mmap_min_addr == CONFIG_DEFAULT_MMAP_MIN_ADDR)
#pragma message "kbase_mmap_min_addr compiled to CONFIG_DEFAULT_MMAP_MIN_ADDR, no runtime update!"
#endif
#else /* CONFIG_MMU */
#define kbase_mmap_min_addr (0UL)
#pragma message "kbase_mmap_min_addr compiled to (0UL), no runtime update!"
#endif /* CONFIG_MMU */
#endif /* KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE */
#include <linux/mm.h>
#if !((KERNEL_VERSION(6, 3, 0) <= LINUX_VERSION_CODE) || \
((KERNEL_VERSION(6, 1, 25) <= LINUX_VERSION_CODE) && defined(__ANDROID_COMMON_KERNEL__)))
static inline void vm_flags_set(struct vm_area_struct *vma, vm_flags_t flags)
{
vma->vm_flags |= flags;
}
static inline void vm_flags_clear(struct vm_area_struct *vma, vm_flags_t flags)
{
vma->vm_flags &= ~flags;
}
#endif
#endif /* _VERSION_COMPAT_DEFS_H_ */
3.2 错误信息如下:
drivers/rknpu/rknpu_devfreq.c:22:10: error: 'MONITOR_TYPE_DEV' undeclared here (not in a function); did you mean 'MONITOR_TPYE_DEV'?
22 | .type = MONITOR_TYPE_DEV,
解决办法:在rknpu_devfreq.c 第22行,将MONITOR_TYPE_DEV修改为MONITOR_TPYE_DEV
3.3 错误信息如下:
drivers/rknpu/rknpu_devfreq.c:732:2: error: implicit declaration of function 'rockchip_uninit_opp_table'; did you mean 'rockchip_init_opp_table'? [-Werror=implicit-function-declaration] 732 | rockchip_uninit_opp_table(dev, &rknpu_dev->opp_info);
解决办法:在rockchip_opp_select.h下添加以下内容
/*
* Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __SOC_ROCKCHIP_OPP_SELECT_H
#define __SOC_ROCKCHIP_OPP_SELECT_H
#define VOLT_RM_TABLE_END ~1
#define OPP_INTERMEDIATE_MASK 0x3f
#define OPP_INTERMEDIATE_RATE BIT(0)
#define OPP_SCALING_UP_RATE BIT(1)
#define OPP_SCALING_UP_INTER (OPP_INTERMEDIATE_RATE | OPP_SCALING_UP_RATE)
#define OPP_SCALING_DOWN_INTER OPP_INTERMEDIATE_RATE
#define OPP_LENGTH_LOW BIT(2)
struct rockchip_opp_info;
struct volt_rm_table {
int volt;
int rm;
};
struct rockchip_opp_data {
int (*get_soc_info)(struct device *dev, struct device_node *np,
int *bin, int *process);
int (*set_soc_info)(struct device *dev, struct device_node *np,
int bin, int process, int volt_sel);
int (*set_read_margin)(struct device *dev,
struct rockchip_opp_info *opp_info,
u32 rm);
};
struct pvtpll_opp_table {
unsigned long rate;
unsigned long u_volt;
unsigned long u_volt_min;
unsigned long u_volt_max;
unsigned long u_volt_mem;
unsigned long u_volt_mem_min;
unsigned long u_volt_mem_max;
};
struct rockchip_opp_info {
struct device *dev;
struct pvtpll_opp_table *opp_table;
const struct rockchip_opp_data *data;
struct volt_rm_table *volt_rm_tbl;
struct regmap *grf;
struct regmap *dsu_grf;
struct clk_bulk_data *clks;
struct clk *scmi_clk;
/* The threshold frequency for set intermediate rate */
unsigned long intermediate_threshold_freq;
unsigned int pvtpll_avg_offset;
unsigned int pvtpll_min_rate;
unsigned int pvtpll_volt_step;
int num_clks;
/* The read margin for low voltage */
u32 low_rm;
u32 current_rm;
u32 target_rm;
};
#if IS_ENABLED(CONFIG_ROCKCHIP_OPP)
int rockchip_of_get_leakage(struct device *dev, char *lkg_name, int *leakage);
void rockchip_of_get_lkg_sel(struct device *dev, struct device_node *np,
char *lkg_name, int process,
int *volt_sel, int *scale_sel);
void rockchip_pvtpll_calibrate_opp(struct rockchip_opp_info *info);
void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
char *reg_name, int bin, int process,
int *volt_sel, int *scale_sel);
void rockchip_of_get_bin_sel(struct device *dev, struct device_node *np,
int bin, int *scale_sel);
void rockchip_of_get_bin_volt_sel(struct device *dev, struct device_node *np,
int bin, int *bin_volt_sel);
int rockchip_nvmem_cell_read_u8(struct device_node *np, const char *cell_id,
u8 *val);
int rockchip_nvmem_cell_read_u16(struct device_node *np, const char *cell_id,
u16 *val);
int rockchip_get_volt_rm_table(struct device *dev, struct device_node *np,
char *porp_name, struct volt_rm_table **table);
void rockchip_get_opp_data(const struct of_device_id *matches,
struct rockchip_opp_info *info);
int rockchip_get_soc_info(struct device *dev, struct device_node *np, int *bin,
int *process);
void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name,
char *reg_name, int bin, int process,
int *scale, int *volt_sel);
struct opp_table *rockchip_set_opp_prop_name(struct device *dev, int process,
int volt_sel);
struct opp_table *rockchip_set_opp_supported_hw(struct device *dev,
struct device_node *np,
int bin, int volt_sel);
int rockchip_adjust_power_scale(struct device *dev, int scale);
int rockchip_get_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt, u32 *target_rm);
int rockchip_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info, u32 rm,
bool is_set_rm);
int rockchip_init_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
char *reg_name);
int rockchip_set_intermediate_rate(struct device *dev,
struct rockchip_opp_info *opp_info,
struct clk *clk, unsigned long old_freq,
unsigned long new_freq, bool is_scaling_up,
bool is_set_clk);
int rockchip_init_opp_table(struct device *dev,
struct rockchip_opp_info *info,
char *lkg_name, char *reg_name);
void rockchip_uninit_opp_table(struct device *dev,
struct rockchip_opp_info *info);
int rockchip_opp_dump_cur_state(struct device *dev);
#else
static inline int rockchip_of_get_leakage(struct device *dev, char *lkg_name,
int *leakage)
{
return -EOPNOTSUPP;
}
static inline void rockchip_of_get_lkg_sel(struct device *dev,
struct device_node *np,
char *lkg_name, int process,
int *volt_sel, int *scale_sel)
{
}
static inline void rockchip_pvtpll_calibrate_opp(struct rockchip_opp_info *info)
{
}
static inline void rockchip_of_get_pvtm_sel(struct device *dev,
struct device_node *np,
char *reg_name, int bin, int process,
int *volt_sel, int *scale_sel)
{
}
static inline void rockchip_of_get_bin_sel(struct device *dev,
struct device_node *np, int bin,
int *scale_sel)
{
}
static inline void rockchip_of_get_bin_volt_sel(struct device *dev,
struct device_node *np,
int bin, int *bin_volt_sel)
{
}
static inline int rockchip_nvmem_cell_read_u8(struct device_node *np,
const char *cell_id, u8 *val)
{
return -EOPNOTSUPP;
}
static inline int rockchip_nvmem_cell_read_u16(struct device_node *np,
const char *cell_id, u16 *val)
{
return -EOPNOTSUPP;
}
static inline int rockchip_get_volt_rm_table(struct device *dev,
struct device_node *np,
char *porp_name,
struct volt_rm_table **table)
{
return -EOPNOTSUPP;
}
static inline void rockchip_get_opp_data(const struct of_device_id *matches,
struct rockchip_opp_info *info)
{
}
static inline int rockchip_get_soc_info(struct device *dev,
struct device_node *np, int *bin,
int *process)
{
return -EOPNOTSUPP;
}
static inline void rockchip_get_scale_volt_sel(struct device *dev,
char *lkg_name, char *reg_name,
int bin, int process, int *scale,
int *volt_sel)
{
}
static inline struct opp_table *rockchip_set_opp_prop_name(struct device *dev,
int process,
int volt_sel)
{
return ERR_PTR(-EOPNOTSUPP);
}
static inline struct opp_table *rockchip_set_opp_supported_hw(struct device *dev,
struct device_node *np,
int bin, int volt_sel)
{
return ERR_PTR(-EOPNOTSUPP);
}
static inline int rockchip_adjust_power_scale(struct device *dev, int scale)
{
return -EOPNOTSUPP;
}
static inline int rockchip_get_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt, u32 *target_rm)
{
return -EOPNOTSUPP;
}
static inline int rockchip_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
u32 rm, bool is_set_rm)
{
return -EOPNOTSUPP;
}
static inline int rockchip_init_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
char *reg_name)
{
return -EOPNOTSUPP;
}
static inline int
rockchip_set_intermediate_rate(struct device *dev,
struct rockchip_opp_info *opp_info,
struct clk *clk, unsigned long old_freq,
unsigned long new_freq, bool is_scaling_up,
bool is_set_clk)
{
return -EOPNOTSUPP;
}
static inline int rockchip_init_opp_table(struct device *dev,
struct rockchip_opp_info *info,
char *lkg_name, char *reg_name)
{
return -EOPNOTSUPP;
}
static inline int rockchip_opp_dump_cur_state(struct device *dev)
{
return -EOPNOTSUPP;
}
static inline void rockchip_uninit_opp_table(struct device *dev,
struct rockchip_opp_info *info)
{
}
#endif /* CONFIG_ROCKCHIP_OPP */
#endif
在rockchip_opp_select.c下添加以下内容
void rockchip_uninit_opp_table(struct device *dev, struct rockchip_opp_info *info)
{
struct opp_table *opp_table;
if (info) {
kfree(info->opp_table);
info->opp_table = NULL;
devm_kfree(dev, info->clks);
info->clks = NULL;
devm_kfree(dev, info->volt_rm_tbl);
info->volt_rm_tbl = NULL;
}
opp_table = dev_pm_opp_get_opp_table(dev);
if (IS_ERR(opp_table))
return;
dev_pm_opp_of_remove_table(dev);
if (opp_table->prop_name)
dev_pm_opp_put_prop_name(opp_table);
if (opp_table->supported_hw)
dev_pm_opp_put_supported_hw(opp_table);
dev_pm_opp_put_opp_table(opp_table);
}
EXPORT_SYMBOL(rockchip_uninit_opp_table);
4.验证版本信息
如图所示,NPU版本为0.9.8,SDK版本是2.3.0