driver: rknpu: Update rknpu driver, version: 0.8.2

* Add auto power on/off support for rknpu
* Add freq/volt node to unify queries and settings

Signed-off-by: Felix Zeng <felix.zeng@rock-chips.com>
Change-Id: Ib55f7ccb7abff51bd36194449bd6c315fcec91b2
This commit is contained in:
Felix Zeng
2022-08-09 18:07:49 +08:00
committed by Tao Huang
parent 0e45c6e151
commit 628387f68d
3 changed files with 339 additions and 92 deletions

View File

@@ -30,10 +30,10 @@
#define DRIVER_NAME "rknpu"
#define DRIVER_DESC "RKNPU driver"
#define DRIVER_DATE "20220803"
#define DRIVER_DATE "20220826"
#define DRIVER_MAJOR 0
#define DRIVER_MINOR 8
#define DRIVER_PATCHLEVEL 0
#define DRIVER_PATCHLEVEL 2
#define LOG_TAG "RKNPU"
@@ -123,6 +123,7 @@ struct rknpu_device {
struct ipa_power_model_data *model_data;
struct thermal_cooling_device *devfreq_cooling;
struct devfreq *devfreq;
unsigned long ondemand_freq;
#ifndef FPGA_PLATFORM
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
struct rockchip_opp_info opp_info;
@@ -141,7 +142,6 @@ struct rknpu_device {
atomic_t cmdline_power_refcount;
struct delayed_work power_off_work;
struct workqueue_struct *power_off_wq;
bool is_powered;
struct rknpu_debugger debugger;
struct hrtimer timer;
ktime_t kt;
@@ -150,8 +150,10 @@ struct rknpu_device {
uint32_t sram_size;
void __iomem *sram_base_io;
struct rknpu_mm *sram_mm;
unsigned long power_put_delay;
};
int rknpu_action(struct rknpu_device *rknpu_dev, struct rknpu_action *args);
int rknpu_power_get(struct rknpu_device *rknpu_dev);
int rknpu_power_put(struct rknpu_device *rknpu_dev);
#endif /* __LINUX_RKNPU_DRV_H_ */

View File

@@ -9,14 +9,23 @@
#include <linux/syscalls.h>
#include <linux/debugfs.h>
#include <linux/proc_fs.h>
#include <linux/devfreq.h>
#include <linux/clk.h>
#include <asm/div64.h>
#ifndef FPGA_PLATFORM
#include <../drivers/devfreq/governor.h>
#endif
#include "rknpu_drv.h"
#include "rknpu_mm.h"
#include "rknpu_reset.h"
#include "rknpu_debugger.h"
#define RKNPU_DEBUGGER_ROOT_NAME "rknpu"
#if defined(CONFIG_ROCKCHIP_RKNPU_DEBUG_FS) || \
defined(CONFIG_ROCKCHIP_RKNPU_PROC_FS)
static int rknpu_version_show(struct seq_file *m, void *data)
{
seq_printf(m, "%s: v%d.%d.%d\n", DRIVER_DESC, DRIVER_MAJOR,
@@ -71,7 +80,7 @@ static int rknpu_power_show(struct seq_file *m, void *data)
struct rknpu_device *rknpu_dev =
container_of(debugger, struct rknpu_device, debugger);
if (rknpu_dev->is_powered)
if (atomic_read(&rknpu_dev->power_refcount) > 0)
seq_puts(m, "on\n");
else
seq_puts(m, "off\n");
@@ -87,7 +96,6 @@ static ssize_t rknpu_power_set(struct file *file, const char __user *ubuf,
struct rknpu_debugger *debugger = node->debugger;
struct rknpu_device *rknpu_dev =
container_of(debugger, struct rknpu_device, debugger);
struct rknpu_action args;
char buf[8];
if (len > sizeof(buf) - 1)
@@ -98,21 +106,19 @@ static ssize_t rknpu_power_set(struct file *file, const char __user *ubuf,
if (strcmp(buf, "on") == 0) {
atomic_inc(&rknpu_dev->cmdline_power_refcount);
args.flags = RKNPU_POWER_ON;
rknpu_action(rknpu_dev, &args);
rknpu_power_get(rknpu_dev);
LOG_INFO("rknpu power is on!");
} else if (strcmp(buf, "off") == 0) {
if (rknpu_dev->is_powered &&
if (atomic_read(&rknpu_dev->power_refcount) > 0 &&
atomic_dec_if_positive(
&rknpu_dev->cmdline_power_refcount) >= 0) {
atomic_sub(
atomic_read(&rknpu_dev->cmdline_power_refcount),
&rknpu_dev->power_refcount);
atomic_set(&rknpu_dev->cmdline_power_refcount, 0);
args.flags = RKNPU_POWER_OFF;
rknpu_action(rknpu_dev, &args);
rknpu_power_put(rknpu_dev);
}
if (!rknpu_dev->is_powered)
if (atomic_read(&rknpu_dev->power_refcount) <= 0)
LOG_INFO("rknpu power is off!");
} else {
LOG_ERROR("rknpu power node params is invalid!");
@@ -121,6 +127,128 @@ static ssize_t rknpu_power_set(struct file *file, const char __user *ubuf,
return len;
}
static int rknpu_power_put_delay_show(struct seq_file *m, void *data)
{
struct rknpu_debugger_node *node = m->private;
struct rknpu_debugger *debugger = node->debugger;
struct rknpu_device *rknpu_dev =
container_of(debugger, struct rknpu_device, debugger);
seq_printf(m, "%lu\n", rknpu_dev->power_put_delay);
return 0;
}
static ssize_t rknpu_power_put_delay_set(struct file *file,
const char __user *ubuf, size_t len,
loff_t *offp)
{
struct seq_file *priv = file->private_data;
struct rknpu_debugger_node *node = priv->private;
struct rknpu_debugger *debugger = node->debugger;
struct rknpu_device *rknpu_dev =
container_of(debugger, struct rknpu_device, debugger);
char buf[16];
unsigned long power_put_delay = 0;
int ret = 0;
if (len > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, len))
return -EFAULT;
buf[len - 1] = '\0';
ret = kstrtoul(buf, 10, &power_put_delay);
if (ret) {
LOG_ERROR("failed to parse power put delay string: %s\n", buf);
return -EFAULT;
}
rknpu_dev->power_put_delay = power_put_delay;
LOG_INFO("set rknpu power put delay time %lums\n",
rknpu_dev->power_put_delay);
return len;
}
static int rknpu_freq_show(struct seq_file *m, void *data)
{
struct rknpu_debugger_node *node = m->private;
struct rknpu_debugger *debugger = node->debugger;
struct rknpu_device *rknpu_dev =
container_of(debugger, struct rknpu_device, debugger);
unsigned long current_freq = 0;
rknpu_power_get(rknpu_dev);
current_freq = clk_get_rate(rknpu_dev->clks[0].clk);
rknpu_power_put(rknpu_dev);
seq_printf(m, "%lu\n", current_freq);
return 0;
}
static ssize_t rknpu_freq_set(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *priv = file->private_data;
struct rknpu_debugger_node *node = priv->private;
struct rknpu_debugger *debugger = node->debugger;
struct rknpu_device *rknpu_dev =
container_of(debugger, struct rknpu_device, debugger);
unsigned long current_freq = 0;
char buf[16];
unsigned long freq = 0;
int ret = 0;
if (len > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, len))
return -EFAULT;
buf[len - 1] = '\0';
ret = kstrtoul(buf, 10, &freq);
if (ret) {
LOG_ERROR("failed to parse freq string: %s\n", buf);
return -EFAULT;
}
if (!rknpu_dev->devfreq)
return -EFAULT;
rknpu_power_get(rknpu_dev);
current_freq = clk_get_rate(rknpu_dev->clks[0].clk);
if (freq != current_freq) {
rknpu_dev->ondemand_freq = freq;
mutex_lock(&rknpu_dev->devfreq->lock);
update_devfreq(rknpu_dev->devfreq);
mutex_unlock(&rknpu_dev->devfreq->lock);
}
rknpu_power_put(rknpu_dev);
return len;
}
static int rknpu_volt_show(struct seq_file *m, void *data)
{
struct rknpu_debugger_node *node = m->private;
struct rknpu_debugger *debugger = node->debugger;
struct rknpu_device *rknpu_dev =
container_of(debugger, struct rknpu_device, debugger);
unsigned long current_volt = 0;
current_volt = regulator_get_voltage(rknpu_dev->vdd);
seq_printf(m, "%lu\n", current_volt);
return 0;
}
static int rknpu_reset_show(struct seq_file *m, void *data)
{
struct rknpu_debugger_node *node = m->private;
@@ -152,7 +280,8 @@ static ssize_t rknpu_reset_set(struct file *file, const char __user *ubuf,
return -EFAULT;
buf[len - 1] = '\0';
if (strcmp(buf, "1") == 0 && rknpu_dev->is_powered)
if (strcmp(buf, "1") == 0 &&
atomic_read(&rknpu_dev->power_refcount) > 0)
rknpu_soft_reset(rknpu_dev);
else if (strcmp(buf, "on") == 0)
rknpu_dev->bypass_soft_reset = 0;
@@ -166,6 +295,10 @@ static struct rknpu_debugger_list rknpu_debugger_root_list[] = {
{ "version", rknpu_version_show, NULL, NULL },
{ "load", rknpu_load_show, NULL, NULL },
{ "power", rknpu_power_show, rknpu_power_set, NULL },
{ "freq", rknpu_freq_show, rknpu_freq_set, NULL },
{ "volt", rknpu_volt_show, NULL, NULL },
{ "delayms", rknpu_power_put_delay_show, rknpu_power_put_delay_set,
NULL },
{ "reset", rknpu_reset_show, rknpu_reset_set, NULL },
#ifdef CONFIG_ROCKCHIP_RKNPU_SRAM
{ "mm", rknpu_mm_dump, NULL, NULL },
@@ -199,6 +332,7 @@ static const struct file_operations rknpu_debugfs_fops = {
.release = single_release,
.write = rknpu_debugger_write,
};
#endif /* #if defined(CONFIG_ROCKCHIP_RKNPU_DEBUG_FS) || defined(CONFIG_ROCKCHIP_RKNPU_PROC_FS) */
#ifdef CONFIG_ROCKCHIP_RKNPU_DEBUG_FS
static int rknpu_debugfs_remove_files(struct rknpu_debugger *debugger)

View File

@@ -41,6 +41,7 @@
#include <soc/rockchip/rockchip_opp_select.h>
#include <soc/rockchip/rockchip_system_monitor.h>
#include <soc/rockchip/rockchip_ipa.h>
#include <../drivers/devfreq/governor.h>
#endif
#include "rknpu_ioctl.h"
@@ -186,46 +187,54 @@ static void rknpu_power_off_delay_work(struct work_struct *power_off_work)
container_of(to_delayed_work(power_off_work),
struct rknpu_device, power_off_work);
mutex_lock(&rknpu_dev->power_lock);
if (atomic_read(&rknpu_dev->power_refcount) == 0 &&
rknpu_dev->is_powered) {
rknpu_dev->is_powered = false;
if (atomic_dec_if_positive(&rknpu_dev->power_refcount) == 0)
rknpu_power_off(rknpu_dev);
}
mutex_unlock(&rknpu_dev->power_lock);
}
int rknpu_action(struct rknpu_device *rknpu_dev, struct rknpu_action *args)
int rknpu_power_get(struct rknpu_device *rknpu_dev)
{
int ret = 0;
cancel_delayed_work(&rknpu_dev->power_off_work);
mutex_lock(&rknpu_dev->power_lock);
if (atomic_inc_return(&rknpu_dev->power_refcount) == 1)
ret = rknpu_power_on(rknpu_dev);
mutex_unlock(&rknpu_dev->power_lock);
return ret;
}
int rknpu_power_put(struct rknpu_device *rknpu_dev)
{
int ret = 0;
mutex_lock(&rknpu_dev->power_lock);
if (atomic_dec_if_positive(&rknpu_dev->power_refcount) == 0)
ret = rknpu_power_off(rknpu_dev);
mutex_unlock(&rknpu_dev->power_lock);
return ret;
}
static int rknpu_power_put_delay(struct rknpu_device *rknpu_dev)
{
mutex_lock(&rknpu_dev->power_lock);
if (atomic_read(&rknpu_dev->power_refcount) == 1)
queue_delayed_work(
rknpu_dev->power_off_wq, &rknpu_dev->power_off_work,
msecs_to_jiffies(rknpu_dev->power_put_delay));
else
atomic_dec_if_positive(&rknpu_dev->power_refcount);
mutex_unlock(&rknpu_dev->power_lock);
return 0;
}
static int rknpu_action(struct rknpu_device *rknpu_dev,
struct rknpu_action *args)
{
int ret = -EINVAL;
switch (args->flags) {
case RKNPU_POWER_ON:
atomic_inc(&rknpu_dev->power_refcount);
mutex_lock(&rknpu_dev->power_lock);
if (!rknpu_dev->is_powered) {
rknpu_dev->is_powered = true;
ret = rknpu_power_on(rknpu_dev);
}
mutex_unlock(&rknpu_dev->power_lock);
break;
case RKNPU_POWER_OFF:
if (rknpu_dev->is_powered &&
atomic_dec_if_positive(&rknpu_dev->power_refcount) == 0)
queue_delayed_work(rknpu_dev->power_off_wq,
&rknpu_dev->power_off_work,
msecs_to_jiffies(1000));
break;
default:
/* default open rknpu power to compatible with librknnrt.so version before 1.2.0 */
mutex_lock(&rknpu_dev->power_lock);
if (!rknpu_dev->is_powered) {
atomic_inc(&rknpu_dev->power_refcount);
rknpu_dev->is_powered = true;
ret = rknpu_power_on(rknpu_dev);
}
mutex_unlock(&rknpu_dev->power_lock);
}
switch (args->flags) {
case RKNPU_GET_HW_VERSION:
ret = rknpu_get_hw_version(rknpu_dev, &args->value);
@@ -234,13 +243,13 @@ int rknpu_action(struct rknpu_device *rknpu_dev, struct rknpu_action *args)
ret = rknpu_get_drv_version(&args->value);
break;
case RKNPU_GET_FREQ:
args->value = rknpu_dev->current_freq;
args->value = clk_get_rate(rknpu_dev->clks[0].clk);
ret = 0;
break;
case RKNPU_SET_FREQ:
break;
case RKNPU_GET_VOLT:
args->value = rknpu_dev->current_volt;
args->value = regulator_get_voltage(rknpu_dev->vdd);
ret = 0;
break;
case RKNPU_SET_VOLT:
@@ -354,9 +363,12 @@ static int rknpu_action_ioctl(struct rknpu_device *rknpu_dev,
static long rknpu_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
{
long ret = 0;
long ret = -EINVAL;
struct rknpu_device *rknpu_dev =
container_of(file->private_data, struct rknpu_device, miscdev);
rknpu_power_get(rknpu_dev);
switch (cmd) {
case IOCTL_RKNPU_ACTION:
ret = rknpu_action_ioctl(rknpu_dev, arg);
@@ -378,6 +390,9 @@ static long rknpu_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
default:
break;
}
rknpu_power_put_delay(rknpu_dev);
return ret;
}
const struct file_operations rknpu_fops = {
@@ -399,17 +414,42 @@ static const struct vm_operations_struct rknpu_gem_vm_ops = {
};
static int rknpu_action_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
struct drm_file *file_priv)
{
struct rknpu_device *rknpu_dev = dev_get_drvdata(dev->dev);
return rknpu_action(rknpu_dev, (struct rknpu_action *)data);
}
#define RKNPU_IOCTL(func) \
static int __##func(struct drm_device *dev, void *data, \
struct drm_file *file_priv) \
{ \
struct rknpu_device *rknpu_dev = dev_get_drvdata(dev->dev); \
int ret = -EINVAL; \
rknpu_power_get(rknpu_dev); \
ret = func(dev, data, file_priv); \
rknpu_power_put_delay(rknpu_dev); \
return ret; \
}
RKNPU_IOCTL(rknpu_action_ioctl);
RKNPU_IOCTL(rknpu_submit_ioctl);
RKNPU_IOCTL(rknpu_gem_create_ioctl);
RKNPU_IOCTL(rknpu_gem_map_ioctl);
RKNPU_IOCTL(rknpu_gem_destroy_ioctl);
RKNPU_IOCTL(rknpu_gem_sync_ioctl);
static const struct drm_ioctl_desc rknpu_ioctls[] = {
DRM_IOCTL_DEF_DRV(RKNPU_ACTION, rknpu_action_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_SUBMIT, rknpu_submit_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_MEM_CREATE, rknpu_gem_create_ioctl,
DRM_IOCTL_DEF_DRV(RKNPU_ACTION, __rknpu_action_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_SUBMIT, __rknpu_submit_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_MEM_CREATE, __rknpu_gem_create_ioctl,
DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_MEM_MAP, rknpu_gem_map_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_MEM_DESTROY, rknpu_gem_destroy_ioctl,
DRM_IOCTL_DEF_DRV(RKNPU_MEM_MAP, __rknpu_gem_map_ioctl,
DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_MEM_SYNC, rknpu_gem_sync_ioctl,
DRM_IOCTL_DEF_DRV(RKNPU_MEM_DESTROY, __rknpu_gem_destroy_ioctl,
DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(RKNPU_MEM_SYNC, __rknpu_gem_sync_ioctl,
DRM_RENDER_ALLOW),
};
@@ -466,14 +506,6 @@ static struct drm_driver rknpu_drm_driver = {
.patchlevel = DRIVER_PATCHLEVEL,
};
static int rknpu_action_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct rknpu_device *rknpu_dev = dev_get_drvdata(dev->dev);
return rknpu_action(rknpu_dev, (struct rknpu_action *)data);
}
#endif
static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)
@@ -915,6 +947,8 @@ static int npu_devfreq_target(struct device *dev, unsigned long *freq,
rknpu_dev->devfreq->last_status.current_frequency =
*freq;
rknpu_dev->current_volt = opp_volt;
LOG_DEV_INFO(dev, "set rknpu freq: %lu, volt: %lu\n",
rknpu_dev->current_freq, rknpu_dev->current_volt);
}
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info);
@@ -999,6 +1033,9 @@ static int npu_devfreq_target(struct device *dev, unsigned long *target_freq,
}
rknpu_dev->current_volt = volt;
LOG_DEV_INFO(dev, "set rknpu freq: %lu, volt: %lu\n",
rknpu_dev->current_freq, rknpu_dev->current_volt);
return ret;
}
#endif
@@ -1025,6 +1062,30 @@ static struct devfreq_dev_profile npu_devfreq_profile = {
.get_cur_freq = npu_devfreq_get_cur_freq,
};
static int devfreq_rknpu_ondemand_func(struct devfreq *df, unsigned long *freq)
{
struct rknpu_device *rknpu_dev = df->data;
if (rknpu_dev)
*freq = rknpu_dev->ondemand_freq;
else
*freq = df->previous_freq;
return 0;
}
static int devfreq_rknpu_ondemand_handler(struct devfreq *devfreq,
unsigned int event, void *data)
{
return 0;
}
static struct devfreq_governor devfreq_rknpu_ondemand = {
.name = "rknpu_ondemand",
.get_target_freq = devfreq_rknpu_ondemand_func,
.event_handler = devfreq_rknpu_ondemand_handler,
};
static unsigned long npu_get_static_power(struct devfreq *devfreq,
unsigned long voltage)
{
@@ -1130,11 +1191,18 @@ static int rknpu_devfreq_init(struct rknpu_device *rknpu_dev)
dev_pm_opp_put(opp);
dp->initial_freq = rknpu_dev->current_freq;
rknpu_dev->devfreq =
devm_devfreq_add_device(dev, dp, "userspace", NULL);
ret = devfreq_add_governor(&devfreq_rknpu_ondemand);
if (ret) {
LOG_DEV_ERROR(dev, "failed to add rknpu_ondemand governor\n");
goto err_remove_table;
}
rknpu_dev->devfreq = devm_devfreq_add_device(dev, dp, "rknpu_ondemand",
(void *)rknpu_dev);
if (IS_ERR(rknpu_dev->devfreq)) {
LOG_DEV_ERROR(dev, "failed to add devfreq\n");
return PTR_ERR(rknpu_dev->devfreq);
ret = PTR_ERR(rknpu_dev->devfreq);
goto err_remove_governor;
}
devm_devfreq_register_opp_notifier(dev, rknpu_dev->devfreq);
@@ -1177,6 +1245,15 @@ static int rknpu_devfreq_init(struct rknpu_device *rknpu_dev)
out:
return 0;
err_remove_governor:
devfreq_remove_governor(&devfreq_rknpu_ondemand);
err_remove_table:
dev_pm_opp_of_remove_table(dev);
rknpu_dev->devfreq = NULL;
return ret;
}
#else
@@ -1249,11 +1326,18 @@ static int rknpu_devfreq_init(struct rknpu_device *rknpu_dev)
}
dp->initial_freq = rknpu_dev->current_freq;
rknpu_dev->devfreq =
devm_devfreq_add_device(dev, dp, "userspace", NULL);
ret = devfreq_add_governor(&devfreq_rknpu_ondemand);
if (ret) {
LOG_DEV_ERROR(dev, "failed to add rknpu_ondemand governor\n");
goto err_remove_table;
}
rknpu_dev->devfreq = devm_devfreq_add_device(dev, dp, "rknpu_ondemand",
(void *)rknpu_dev);
if (IS_ERR(rknpu_dev->devfreq)) {
LOG_DEV_ERROR(dev, "failed to add devfreq\n");
return PTR_ERR(rknpu_dev->devfreq);
ret = PTR_ERR(rknpu_dev->devfreq);
goto err_remove_governor;
}
devm_devfreq_register_opp_notifier(dev, rknpu_dev->devfreq);
@@ -1295,8 +1379,30 @@ static int rknpu_devfreq_init(struct rknpu_device *rknpu_dev)
out:
return 0;
err_remove_governor:
devfreq_remove_governor(&devfreq_rknpu_ondemand);
err_remove_table:
dev_pm_opp_of_remove_table(dev);
rknpu_dev->devfreq = NULL;
return ret;
}
#endif
static int rknpu_devfreq_remove(struct rknpu_device *rknpu_dev)
{
if (rknpu_dev->devfreq) {
devfreq_unregister_opp_notifier(rknpu_dev->dev,
rknpu_dev->devfreq);
dev_pm_opp_of_remove_table(rknpu_dev->dev);
devfreq_remove_governor(&devfreq_rknpu_ondemand);
}
return 0;
}
#endif
static int rknpu_register_irq(struct platform_device *pdev,
@@ -1573,12 +1679,7 @@ static int rknpu_probe(struct platform_device *pdev)
if (ret) {
LOG_DEV_ERROR(dev,
"failed to allocate fence context for rknpu\n");
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
goto err_remove_drm;
#endif
#ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP
goto err_remove_misc;
#endif
goto err_remove_drv;
}
#endif
@@ -1601,25 +1702,23 @@ static int rknpu_probe(struct platform_device *pdev)
}
ret = rknpu_power_on(rknpu_dev);
if (ret) {
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
goto err_remove_drm;
#endif
#ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP
goto err_remove_misc;
#endif
}
if (ret)
goto err_remove_drv;
#ifndef FPGA_PLATFORM
rknpu_devfreq_init(rknpu_dev);
ret = rknpu_devfreq_init(rknpu_dev);
if (ret)
goto err_remove_drv;
#endif
// set default power put delay to 3s
rknpu_dev->power_put_delay = 3000;
rknpu_dev->power_off_wq =
create_freezable_workqueue("rknpu_power_off_wq");
if (!rknpu_dev->power_off_wq) {
LOG_DEV_ERROR(dev, "rknpu couldn't create power_off workqueue");
ret = -ENOMEM;
goto err_remove_wq;
goto err_devfreq_remove;
}
INIT_DEFERRABLE_WORK(&rknpu_dev->power_off_work,
rknpu_power_off_delay_work);
@@ -1636,7 +1735,6 @@ static int rknpu_probe(struct platform_device *pdev)
}
rknpu_power_off(rknpu_dev);
rknpu_dev->is_powered = false;
atomic_set(&rknpu_dev->power_refcount, 0);
atomic_set(&rknpu_dev->cmdline_power_refcount, 0);
@@ -1645,16 +1743,22 @@ static int rknpu_probe(struct platform_device *pdev)
return 0;
err_remove_wq:
destroy_workqueue(rknpu_dev->power_off_wq);
err_devfreq_remove:
#ifndef FPGA_PLATFORM
rknpu_devfreq_remove(rknpu_dev);
#endif
err_remove_drv:
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
err_remove_drm:
rknpu_drm_remove(rknpu_dev);
#endif
#ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP
err_remove_misc:
misc_deregister(&(rknpu_dev->miscdev));
#endif
err_remove_wq:
destroy_workqueue(rknpu_dev->power_off_wq);
return ret;
}
@@ -1683,8 +1787,15 @@ static int rknpu_remove(struct platform_device *pdev)
#ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP
misc_deregister(&(rknpu_dev->miscdev));
#endif
if (rknpu_dev->is_powered)
#ifndef FPGA_PLATFORM
rknpu_devfreq_remove(rknpu_dev);
#endif
mutex_lock(&rknpu_dev->power_lock);
if (atomic_read(&rknpu_dev->power_refcount) > 0)
rknpu_power_off(rknpu_dev);
mutex_unlock(&rknpu_dev->power_lock);
if (rknpu_dev->multiple_domains) {
if (rknpu_dev->genpd_dev_npu0)