mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
nvdla: Replace deprecated nvhost_module* APIs
Remove dependencies on the following deprecated nvhost API functions by implementing their functionality directly in the NVDLA driver: 1. nvhost_module_init: Replaced with direct implementation in nvdla_module_init: - Get clock resources and set clock rates - Initialize reset control - Set up power management runtime - Create debugfs entries 2. nvhost_module_deinit: Replaced with direct implementation in nvdla_module_deinit: - Disable power management runtime - Free falcon firmware if present - Clean up debugfs entries 3. nvhost_module_reset: Replaced with direct implementation in nvdla_module_reset: - Handle prepare_poweroff callback - Acquire and release reset control - Load clock gating registers - Handle finalize_poweron callback 4. nvhost_module_busy: Replaced with direct implementation in nvdla_module_busy: - Get PM runtime sync - Handle PM runtime errors 5. nvhost_module_idle and nvhost_module_idle_mult: Replaced with direct implementations: - Mark last busy for PM runtime - Handle autosuspend or regular PM runtime put 6. nvhost_module_pm_ops: Replaced with custom nvdla_pm_ops structure: - Implement nvdla_runtime_suspend and nvdla_runtime_resume - Implement nvdla_suspend and nvdla_resume - Configure SET_RUNTIME_PM_OPS and SET_SYSTEM_SLEEP_PM_OPS 7. nvhost_module_load_regs: Replaced with nvdla_module_load_regs: - Implement register manipulation with direct memory mapped I/O - Use writel instead of host1x_writel Bug 4921620 Jira HOSTX-5963 Change-Id: I3006a92a05966da138da31730e97f74f786c9d0c Signed-off-by: Mainak Sen <msen@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3321246 Reviewed-by: Arvind M <am@nvidia.com> Reviewed-by: Mitch Harwell <mharwell@nvidia.com> GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "../../dla_queue.h"
|
||||
#include "../../nvdla_debug.h"
|
||||
#include "../fw/nvdla_falcon.h"
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
@@ -19,6 +20,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
uint32_t nvdla_device_register_read(struct platform_device *pdev,
|
||||
uint32_t reg)
|
||||
@@ -126,6 +128,7 @@ int32_t nvdla_module_init(struct platform_device *pdev)
|
||||
int32_t err;
|
||||
struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
unsigned int num_clks;
|
||||
|
||||
pdata->host1x = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!pdata->host1x) {
|
||||
@@ -153,16 +156,62 @@ int32_t nvdla_module_init(struct platform_device *pdev)
|
||||
pdata->aperture[i] = regs;
|
||||
}
|
||||
|
||||
err = nvhost_module_init(pdev);
|
||||
if (err) {
|
||||
nvdla_dbg_err(pdev, "Failed to init module (err: %x)", err);
|
||||
err = devm_clk_bulk_get_all(&pdev->dev, &pdata->clks);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to get clocks %d\n", err);
|
||||
return err;
|
||||
}
|
||||
pdata->num_clks = err;
|
||||
num_clks = err;
|
||||
|
||||
for (i = 0; i < num_clks; i++) {
|
||||
err = clk_set_rate(pdata->clks[i].clk, ULONG_MAX);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to set clock rate!\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
pdata->reset_control = devm_reset_control_get_exclusive_released(&pdev->dev, NULL);
|
||||
if (IS_ERR(pdata->reset_control)) {
|
||||
dev_err(&pdev->dev, "failed to get reset\n");
|
||||
return PTR_ERR(pdata->reset_control);
|
||||
}
|
||||
|
||||
err = reset_control_acquire(pdata->reset_control);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to acquire reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = clk_bulk_prepare_enable(num_clks, pdata->clks);
|
||||
if (err < 0) {
|
||||
reset_control_release(pdata->reset_control);
|
||||
dev_err(&pdev->dev, "failed to enabled clocks: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
reset_control_reset(pdata->reset_control);
|
||||
clk_bulk_disable_unprepare(num_clks, pdata->clks);
|
||||
reset_control_release(pdata->reset_control);
|
||||
|
||||
if (pdata->autosuspend_delay) {
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, pdata->autosuspend_delay);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
if (!pm_runtime_enabled(&pdev->dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
pdata->debugfs = debugfs_create_dir(pdev->dev.of_node->name, NULL);
|
||||
|
||||
err = nvdla_client_device_init(pdev);
|
||||
if (err) {
|
||||
nvdla_dbg_err(pdev, "Failed to client device (err: %x)", err);
|
||||
nvhost_module_deinit(pdev);
|
||||
/* Clean up in case of error */
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
debugfs_remove_recursive(pdata->debugfs);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -171,8 +220,19 @@ int32_t nvdla_module_init(struct platform_device *pdev)
|
||||
|
||||
void nvdla_module_deinit(struct platform_device *pdev)
|
||||
{
|
||||
struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
|
||||
struct falcon *falcon = pdata->falcon_data;
|
||||
|
||||
nvdla_client_device_release(pdev);
|
||||
nvhost_module_deinit(pdev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
if (falcon) {
|
||||
dma_free_coherent(&pdev->dev, falcon->firmware.size,
|
||||
falcon->firmware.virt, falcon->firmware.iova);
|
||||
falcon_exit(falcon);
|
||||
}
|
||||
|
||||
debugfs_remove_recursive(pdata->debugfs);
|
||||
}
|
||||
|
||||
int32_t nvdla_module_client_register(struct platform_device *pdev,
|
||||
@@ -189,47 +249,182 @@ void nvdla_module_client_unregister(struct platform_device *pdev,
|
||||
|
||||
int32_t nvdla_module_busy(struct platform_device *pdev)
|
||||
{
|
||||
return nvhost_module_busy(pdev);
|
||||
int err;
|
||||
|
||||
err = pm_runtime_get_sync(&pdev->dev);
|
||||
if (err < 0) {
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nvdla_module_idle(struct platform_device *pdev)
|
||||
{
|
||||
nvhost_module_idle(pdev);
|
||||
nvdla_module_idle_mult(pdev, 1);
|
||||
}
|
||||
|
||||
void nvdla_module_idle_mult(struct platform_device *pdev, int32_t refs)
|
||||
{
|
||||
nvhost_module_idle_mult(pdev, refs);
|
||||
struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
|
||||
|
||||
while (refs--) {
|
||||
pm_runtime_mark_last_busy(&pdev->dev);
|
||||
if (pdata->autosuspend_delay)
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
else
|
||||
pm_runtime_put(&pdev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void nvdla_module_load_regs(struct platform_device *pdev, bool prod)
|
||||
{
|
||||
struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
|
||||
struct nvhost_gating_register *regs = pdata->engine_cg_regs;
|
||||
|
||||
if (!regs)
|
||||
return;
|
||||
|
||||
while (regs->addr) {
|
||||
if (prod) {
|
||||
void __iomem *addr = pdata->aperture[0] + regs->addr;
|
||||
|
||||
writel(regs->prod, addr);
|
||||
} else {
|
||||
void __iomem *addr = pdata->aperture[0] + regs->addr;
|
||||
|
||||
writel(regs->disable, addr);
|
||||
}
|
||||
regs++;
|
||||
}
|
||||
}
|
||||
|
||||
void nvdla_module_reset(struct platform_device *pdev, bool reboot)
|
||||
{
|
||||
nvhost_module_reset(pdev, reboot);
|
||||
struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
|
||||
int err;
|
||||
|
||||
if (reboot)
|
||||
if (pdata->prepare_poweroff)
|
||||
pdata->prepare_poweroff(pdev);
|
||||
|
||||
mutex_lock(&pdata->lock);
|
||||
err = reset_control_acquire(pdata->reset_control);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to acquire reset: %d\n", err);
|
||||
} else {
|
||||
reset_control_reset(pdata->reset_control);
|
||||
reset_control_release(pdata->reset_control);
|
||||
}
|
||||
mutex_unlock(&pdata->lock);
|
||||
|
||||
if (reboot) {
|
||||
/* Load clockgating registers */
|
||||
nvdla_module_load_regs(pdev, pdata->engine_can_cg);
|
||||
|
||||
/* ..and execute engine specific operations (i.e. boot) */
|
||||
if (pdata->finalize_poweron)
|
||||
pdata->finalize_poweron(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Define our own runtime_suspend function for nvdla */
|
||||
static int nvdla_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct nvhost_device_data *pdata = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
if (pdata->prepare_poweroff) {
|
||||
err = pdata->prepare_poweroff(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
clk_bulk_disable_unprepare(pdata->num_clks, pdata->clks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Define our own runtime_resume function for nvdla */
|
||||
static int nvdla_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct nvhost_device_data *pdata = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = clk_bulk_prepare_enable(pdata->num_clks, pdata->clks);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to enabled clocks: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (pdata->poweron_reset)
|
||||
nvdla_module_reset(pdev, false);
|
||||
|
||||
/* Load clockgating registers */
|
||||
nvdla_module_load_regs(pdev, pdata->engine_can_cg);
|
||||
|
||||
if (pdata->finalize_poweron)
|
||||
err = pdata->finalize_poweron(pdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Define our own suspend function for nvdla */
|
||||
static int nvdla_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct nvhost_device_data *pdata = dev_get_drvdata(dev);
|
||||
int err = 0;
|
||||
|
||||
if (pdata->prepare_poweroff) {
|
||||
err = pdata->prepare_poweroff(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
clk_bulk_disable_unprepare(pdata->num_clks, pdata->clks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Define our own resume function for nvdla */
|
||||
static int nvdla_resume(struct device *dev)
|
||||
{
|
||||
return nvdla_runtime_resume(dev);
|
||||
}
|
||||
|
||||
/* Create our own PM operations structure */
|
||||
static const struct dev_pm_ops nvdla_pm_ops = {
|
||||
.runtime_suspend = nvdla_runtime_suspend,
|
||||
.runtime_resume = nvdla_runtime_resume,
|
||||
.suspend = nvdla_suspend,
|
||||
.resume = nvdla_resume,
|
||||
};
|
||||
|
||||
/* Module runtime suspend implementation */
|
||||
int nvdla_module_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct nvhost_device_data *pdata = dev_get_drvdata(dev);
|
||||
struct nvdla_device *nvdla = pdata->private_data;
|
||||
int err;
|
||||
|
||||
if (nvhost_module_pm_ops.runtime_suspend != NULL) {
|
||||
err = nvhost_module_pm_ops.runtime_suspend(dev);
|
||||
/* Call directly to our own runtime_suspend */
|
||||
err = nvdla_runtime_suspend(dev);
|
||||
if (!err && nvdla->icc_write) {
|
||||
err = icc_set_bw(nvdla->icc_write, 0, 0);
|
||||
if (err)
|
||||
dev_warn(&nvdla->pdev->dev,
|
||||
"failed to set icc_write bw: %d\n",
|
||||
err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Module runtime resume implementation */
|
||||
int nvdla_module_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct nvhost_device_data *pdata = dev_get_drvdata(dev);
|
||||
@@ -239,8 +434,8 @@ int nvdla_module_runtime_resume(struct device *dev)
|
||||
u32 emc_kbps;
|
||||
int err;
|
||||
|
||||
if (nvhost_module_pm_ops.runtime_resume != NULL) {
|
||||
err = nvhost_module_pm_ops.runtime_resume(dev);
|
||||
/* Call directly to our own runtime_resume */
|
||||
err = nvdla_runtime_resume(dev);
|
||||
if (!err && nvdla->icc_write) {
|
||||
rate = clk_get_rate(clk);
|
||||
emc_kbps = rate * NVDLA_AXI_DBB_BW_BPC / 1024;
|
||||
@@ -250,13 +445,9 @@ int nvdla_module_runtime_resume(struct device *dev)
|
||||
dev_warn(&nvdla->pdev->dev,
|
||||
"failed to set icc_write bw: %d\n",
|
||||
err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int nvdla_module_suspend(struct device *dev)
|
||||
@@ -265,19 +456,12 @@ int nvdla_module_suspend(struct device *dev)
|
||||
struct nvdla_device *nvdla_dev = pdata->private_data;
|
||||
int err = 0;
|
||||
|
||||
if (nvhost_module_pm_ops.suspend != NULL) {
|
||||
err = nvhost_module_pm_ops.suspend(dev);
|
||||
/* Call directly to our own suspend */
|
||||
err = nvdla_suspend(dev);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "(FAIL) NvHost suspend\n");
|
||||
dev_err(dev, "(FAIL) NVDLA suspend\n");
|
||||
goto fail_nvhost_module_suspend;
|
||||
}
|
||||
} else {
|
||||
err = pm_runtime_force_suspend(dev);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "(FAIL) PM suspend\n");
|
||||
goto fail_nvhost_module_suspend;
|
||||
}
|
||||
}
|
||||
|
||||
if (nvdla_dev->icc_write) {
|
||||
err = icc_set_bw(nvdla_dev->icc_write, 0, 0);
|
||||
@@ -305,19 +489,12 @@ int nvdla_module_resume(struct device *dev)
|
||||
goto fail_not_in_suspend;
|
||||
}
|
||||
|
||||
if (nvhost_module_pm_ops.resume != NULL) {
|
||||
err = nvhost_module_pm_ops.resume(dev);
|
||||
/* Call directly to our own resume */
|
||||
err = nvdla_resume(dev);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "(FAIL) NvHost resume\n");
|
||||
dev_err(dev, "(FAIL) NVDLA resume\n");
|
||||
goto fail_nvhost_module_resume;
|
||||
}
|
||||
} else {
|
||||
err = pm_runtime_force_resume(dev);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "(FAIL) PM resume\n");
|
||||
goto fail_nvhost_module_resume;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -345,25 +522,11 @@ int nvdla_module_prepare_suspend(struct device *dev)
|
||||
goto fail_nvdla_queue_pool_prepare_suspend;
|
||||
}
|
||||
|
||||
/* NvHost prepare suspend - callback */
|
||||
if (nvhost_module_pm_ops.prepare != NULL) {
|
||||
err = nvhost_module_pm_ops.prepare(dev);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "(FAIL) NvHost prepare suspend\n");
|
||||
goto fail_nvhost_module_prepare_suspend;
|
||||
}
|
||||
} else {
|
||||
/* If we took an extra reference, drop it now to prevent
|
||||
* the device from automatically resuming upon system
|
||||
* resume.
|
||||
*/
|
||||
/* Drop runtime reference */
|
||||
pm_runtime_put_sync(dev);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
fail_nvhost_module_prepare_suspend:
|
||||
fail_nvdla_queue_pool_prepare_suspend:
|
||||
fail_already_in_suspend:
|
||||
return err;
|
||||
@@ -374,12 +537,8 @@ void nvdla_module_complete_resume(struct device *dev)
|
||||
struct nvhost_device_data *pdata = dev_get_drvdata(dev);
|
||||
struct nvdla_device *nvdla_dev = pdata->private_data;
|
||||
|
||||
if (nvhost_module_pm_ops.complete != NULL) {
|
||||
nvhost_module_pm_ops.complete(dev);
|
||||
} else {
|
||||
/* Retake reference dropped above */
|
||||
/* Retake reference dropped in prepare */
|
||||
pm_runtime_get_noresume(dev);
|
||||
}
|
||||
|
||||
/* Module is no longer in suspend and has resumed successfully */
|
||||
nvdla_dev->is_suspended = false;
|
||||
@@ -388,6 +547,7 @@ void nvdla_module_complete_resume(struct device *dev)
|
||||
static struct host1x_driver host1x_nvdla_driver = {
|
||||
.driver = {
|
||||
.name = "host1x-nvdla",
|
||||
.pm = &nvdla_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -152,6 +152,19 @@ static int falcon_init(struct falcon *falcon)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* falcon_exit() - Release resources used by falcon
|
||||
*
|
||||
* @falcon: Pointer to falcon structure
|
||||
*
|
||||
* This function releases firmware resources for falcon
|
||||
*/
|
||||
void falcon_exit(struct falcon *falcon)
|
||||
{
|
||||
if (falcon->firmware.firmware)
|
||||
release_firmware(falcon->firmware.firmware);
|
||||
}
|
||||
|
||||
static int falcon_boot(struct falcon *falcon)
|
||||
{
|
||||
unsigned long offset;
|
||||
|
||||
@@ -116,5 +116,6 @@ int nvdla_flcn_intr_init(struct platform_device *pdev);
|
||||
int nvdla_flcn_reload_fw(struct platform_device *pdev);
|
||||
int nvdla_flcn_prepare_poweroff(struct platform_device *pdev);
|
||||
int nvdla_flcn_finalize_poweron(struct platform_device *pdev);
|
||||
void falcon_exit(struct falcon *falcon);
|
||||
|
||||
#endif /* _NVDLA_PORT_FW_FALCON_H_ */
|
||||
Reference in New Issue
Block a user