Skip to content
Snippets Groups Projects
Commit 41f726bd authored by Tomeu Vizoso's avatar Tomeu Vizoso
Browse files

fixup: enable runtime PM

parent d374c042
No related branches found
No related tags found
No related merge requests found
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2024 Tomeu Vizoso <tomeu@tomeuvizoso.net> */
#include <asm-generic/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include "rocket_core.h"
......
......@@ -17,6 +17,7 @@ struct rocket_core {
struct device *dev;
struct rocket_device *rdev;
unsigned int index;
struct device_link *link;
struct reset_control *a_reset;
struct reset_control *h_reset;
......
......@@ -144,11 +144,11 @@ static int rocket_drm_bind(struct device *dev)
if (err)
goto err_drm_dev;
// pm_runtime_use_autosuspend(dev);
// pm_runtime_set_autosuspend_delay(dev, 50); /* ~3 frames */
// pm_runtime_set_active(dev);
// pm_runtime_enable(dev);
// pm_runtime_mark_last_busy(dev);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 50); /* ~3 frames */
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_mark_last_busy(dev);
/*
* Register the DRM device with the core and the connectors with
......@@ -158,6 +158,8 @@ static int rocket_drm_bind(struct device *dev)
if (err < 0)
goto err_pm_runtime;
printk("*** %s: %d dev %s usage_count %d links_count %d\n", __func__, 99, dev_name(dev), atomic_read(&dev->power.usage_count), dev->power.links_count);
return 0;
err_pm_runtime:
......@@ -180,9 +182,9 @@ static void rocket_drm_unbind(struct device *dev)
component_unbind_all(dev, rdev);
// pm_runtime_disable(dev);
pm_runtime_disable(dev);
rocket_device_fini(rdev);
// pm_runtime_set_suspended(dev);
pm_runtime_set_suspended(dev);
drm_dev_put(ddev);
......@@ -200,9 +202,14 @@ static int rocket_core_bind(struct device *dev, struct device *master, void *dat
unsigned int core = rdev->num_cores;
int err;
platform_set_drvdata(to_platform_device(dev), rdev);
rdev->cores[core].rdev = rdev;
rdev->cores[core].dev = dev;
rdev->cores[core].index = core;
rdev->cores[core].link = device_link_add(dev, rdev->cores[0].dev,
DL_FLAG_STATELESS);
rdev->num_cores++;
err = rocket_core_init(&rdev->cores[core]);
......@@ -211,6 +218,15 @@ static int rocket_core_bind(struct device *dev, struct device *master, void *dat
return err;
}
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 50); /* ~3 frames */
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_mark_last_busy(dev);
printk("*** %s: %d dev %s usage_count %d links_count %d\n", __func__, 99, dev_name(dev), atomic_read(&dev->power.usage_count), dev->power.links_count);
return 0;
}
......@@ -220,13 +236,18 @@ static void rocket_core_unbind(struct device *dev, struct device *master, void *
printk("*** %s: %d dev %p\n", __func__, 1, dev);
pm_runtime_disable(dev);
for (unsigned int core = 0; core < rdev->num_cores; core++) {
if (rdev->cores[core].dev == dev) {
rocket_core_fini(&rdev->cores[core]);
device_link_del(rdev->cores[core].link);
break;
}
}
pm_runtime_set_suspended(dev);
printk("*** %s: %d\n", __func__, 99);
}
......@@ -287,14 +308,20 @@ MODULE_DEVICE_TABLE(of, dt_match);
static int rocket_device_runtime_resume(struct device *dev)
{
struct rocket_device *rdev = dev_get_drvdata(dev);
int core;
clk_prepare_enable(rdev->clk_npu);
clk_prepare_enable(rdev->pclk);
printk("*** %s: %d dev %s\n", __func__, 1, dev_name(dev));
for (core = 0; core < rdev->num_cores; core++) {
clk_prepare_enable(rdev->cores[core].a_clk);
clk_prepare_enable(rdev->cores[core].h_clk);
for (unsigned int core = 0; core < rdev->num_cores; core++) {
if (rdev->cores[core].dev == dev) {
printk("*** %s: %d core %d\n", __func__, 2, core);
if (core == 0) {
clk_prepare_enable(rdev->clk_npu);
clk_prepare_enable(rdev->pclk);
}
clk_prepare_enable(rdev->cores[core].a_clk);
clk_prepare_enable(rdev->cores[core].h_clk);
break;
}
}
return 0;
......@@ -303,19 +330,26 @@ static int rocket_device_runtime_resume(struct device *dev)
static int rocket_device_runtime_suspend(struct device *dev)
{
struct rocket_device *rdev = dev_get_drvdata(dev);
int core;
if (!rocket_job_is_idle(rdev))
return -EBUSY;
printk("*** %s: %d dev %s\n", __func__, 1, dev_name(dev));
WARN(1, "");
for (core = 0; core < rdev->num_cores; core++) {
clk_disable_unprepare(rdev->cores[core].a_clk);
clk_disable_unprepare(rdev->cores[core].h_clk);
for (unsigned int core = 0; core < rdev->num_cores; core++) {
if (rdev->cores[core].dev == dev) {
printk("*** %s: %d core %d\n", __func__, 2, core);
if (!rocket_job_is_idle(&rdev->cores[core]))
return -EBUSY;
clk_disable_unprepare(rdev->cores[core].a_clk);
clk_disable_unprepare(rdev->cores[core].h_clk);
if (core == 0) {
clk_disable_unprepare(rdev->pclk);
clk_disable_unprepare(rdev->clk_npu);
}
break;
}
}
clk_disable_unprepare(rdev->pclk);
clk_disable_unprepare(rdev->clk_npu);
return 0;
}
......@@ -329,7 +363,7 @@ static struct platform_driver rocket_driver = {
.remove_new = rocket_remove,
.driver = {
.name = "rocket",
//.pm = pm_ptr(&rocket_pm_ops),
.pm = pm_ptr(&rocket_pm_ops),
.of_match_table = dt_match,
},
};
......
......@@ -607,15 +607,11 @@ void rocket_job_close(struct rocket_file_priv *rocket_priv)
drm_sched_entity_destroy(entity);
}
int rocket_job_is_idle(struct rocket_device *rdev)
int rocket_job_is_idle(struct rocket_core *core)
{
unsigned int core;
for (core = 0; core < rdev->num_cores; core++) {
/* If there are any jobs in any HW queue, we're not idle */
if (atomic_read(&rdev->cores[core].sched.credit_count))
return false;
}
/* If there are any jobs in the HW queue, we're not idle */
if (atomic_read(&core->sched.credit_count))
return false;
return true;
}
......
......@@ -44,6 +44,6 @@ int rocket_job_init(struct rocket_core *core);
void rocket_job_fini(struct rocket_core *core);
int rocket_job_open(struct rocket_file_priv *rocket_priv);
void rocket_job_close(struct rocket_file_priv *rocket_priv);
int rocket_job_is_idle(struct rocket_device *rdev);
int rocket_job_is_idle(struct rocket_core *core);
#endif
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment