From 628387f68dcad4b1fca9c8523bbcf6469f401166 Mon Sep 17 00:00:00 2001 From: Felix Zeng Date: Tue, 9 Aug 2022 18:07:49 +0800 Subject: [PATCH] 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 Change-Id: Ib55f7ccb7abff51bd36194449bd6c315fcec91b2 --- drivers/rknpu/include/rknpu_drv.h | 10 +- drivers/rknpu/rknpu_debugger.c | 152 ++++++++++++++++- drivers/rknpu/rknpu_drv.c | 269 +++++++++++++++++++++--------- 3 files changed, 339 insertions(+), 92 deletions(-) diff --git a/drivers/rknpu/include/rknpu_drv.h b/drivers/rknpu/include/rknpu_drv.h index 126b9e857b38..f7f2dee2c95d 100644 --- a/drivers/rknpu/include/rknpu_drv.h +++ b/drivers/rknpu/include/rknpu_drv.h @@ -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_ */ diff --git a/drivers/rknpu/rknpu_debugger.c b/drivers/rknpu/rknpu_debugger.c index 49a22503d534..4d5bebd7e51f 100644 --- a/drivers/rknpu/rknpu_debugger.c +++ b/drivers/rknpu/rknpu_debugger.c @@ -9,14 +9,23 @@ #include #include #include +#include +#include #include +#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) diff --git a/drivers/rknpu/rknpu_drv.c b/drivers/rknpu/rknpu_drv.c index 48a12595c90e..28cf1f49f26e 100644 --- a/drivers/rknpu/rknpu_drv.c +++ b/drivers/rknpu/rknpu_drv.c @@ -41,6 +41,7 @@ #include #include #include +#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)