From a87d4c6d8acbf3de07aa303793be0f7b63b68d98 Mon Sep 17 00:00:00 2001 From: ys Date: Fri, 28 Oct 2022 03:34:15 -0700 Subject: drive:e24:add runtme pm ops add runtime pm ops Signed-off-by: ys --- drivers/e24/starfive_e24.c | 121 +++++++++++++++++++++++++++++++----------- drivers/e24/starfive_e24_hw.c | 51 +++++++++++------- drivers/e24/starfive_e24_hw.h | 4 ++ 3 files changed, 128 insertions(+), 48 deletions(-) diff --git a/drivers/e24/starfive_e24.c b/drivers/e24/starfive_e24.c index 500f8b42fb23..1c886ba279f3 100644 --- a/drivers/e24/starfive_e24.c +++ b/drivers/e24/starfive_e24.c @@ -277,13 +277,53 @@ static const struct vm_operations_struct e24_vm_ops = { .close = e24_vm_close, }; +static long e24_synchronize(struct e24_device *dev) +{ + + struct e24_comm *queue = dev->queue; + struct e24_dsp_cmd __iomem *cmd = queue->comm; + u32 flags; + unsigned long deadline = jiffies + 10 * HZ; + + do { + flags = __raw_readl(&cmd->flags); + /* memory barrier */ + rmb(); + if (flags == 0x104) + return 0; + + schedule(); + } while (time_before(jiffies, deadline)); + + return -1; +} + static int e24_open(struct inode *inode, struct file *filp) { struct e24_device *e24_dev = container_of(filp->private_data, struct e24_device, miscdev); + int rc = 0; + + rc = pm_runtime_get_sync(e24_dev->dev); + if (rc < 0) + return rc; spin_lock_init(&e24_dev->busy_list_lock); filp->private_data = e24_dev; + mdelay(1); + + return 0; +} + +int e24_release(struct inode *inode, struct file *filp) +{ + struct e24_device *e24_dev = (struct e24_device *)filp->private_data; + int rc = 0; + + rc = pm_runtime_put_sync(e24_dev->dev); + if (rc < 0) + return rc; + return 0; } @@ -600,6 +640,7 @@ static long e24_unmap_request(struct file *filp, struct e24_ioctl_request *rq) if (rq->ioctl_data.in_data_size > E24_DSP_CMD_INLINE_DATA_SIZE) __e24_unshare_block(filp, &rq->in_data_mapping, E24_FLAG_READ); + if (rq->ioctl_data.out_data_size > E24_DSP_CMD_INLINE_DATA_SIZE) { ret = __e24_unshare_block(filp, &rq->out_data_mapping, E24_FLAG_WRITE); @@ -966,6 +1007,7 @@ static const struct file_operations e24_fops = { .compat_ioctl = e24_ioctl, #endif .open = e24_open, + .release = e24_release, .write = mbox_e24_message_write, .mmap = e24_mmap, }; @@ -1065,6 +1107,12 @@ empty: typedef long e24_init_function(struct platform_device *pdev); +static inline void e24_init(struct e24_device *e24_hw) +{ + if (e24_hw->hw_ops->init) + e24_hw->hw_ops->init(e24_hw->hw_arg); +} + static inline void e24_release_e24(struct e24_device *e24_hw) { if (e24_hw->hw_ops->reset) @@ -1103,15 +1151,6 @@ static inline void e24_sendirq_e24(struct e24_device *e24_hw) e24_hw->hw_ops->send_irq(e24_hw->hw_arg); } -int e24_runtime_suspend(struct device *dev) -{ - struct e24_device *e24_dev = dev_get_drvdata(dev); - - e24_halt_e24(e24_dev); - e24_disable_e24(e24_dev); - return 0; -} - irqreturn_t e24_irq_handler(int irq, struct e24_device *e24_hw) { dev_dbg(e24_hw->dev, "%s\n", __func__); @@ -1285,35 +1324,44 @@ static int e24_load_firmware(struct e24_device *e24_dev) static int e24_boot_firmware(struct device *dev) { int ret; - struct e24_device *e24_dev = dev_get_drvdata(dev); - ret = e24_enable_e24(e24_dev); - - if (ret < 0) - return ret; - - e24_halt_e24(e24_dev); - if (e24_dev->firmware_name) { ret = request_firmware(&e24_dev->firmware, e24_dev->firmware_name, e24_dev->dev); - if (ret < 0) - return ret; - - ret = e24_load_firmware(e24_dev); + if (ret < 0) + return ret; - if (ret < 0) - release_firmware(e24_dev->firmware); + ret = e24_load_firmware(e24_dev); + if (ret < 0) { + release_firmware(e24_dev->firmware); + return ret; + } } + release_firmware(e24_dev->firmware); + ret = e24_enable_e24(e24_dev); + if (ret < 0) + return ret; + e24_reset_e24(e24_dev); e24_release_e24(e24_dev); + e24_synchronize(e24_dev); return ret; } +int e24_runtime_suspend(struct device *dev) +{ + struct e24_device *e24_dev = dev_get_drvdata(dev); + + e24_halt_e24(e24_dev); + e24_disable_e24(e24_dev); + + return 0; +} + long e24_init_v0(struct platform_device *pdev) { long ret = -EINVAL; @@ -1376,15 +1424,20 @@ long e24_init_v0(struct platform_device *pdev) goto err_free_map; } - ret = e24_boot_firmware(e24_dev->dev); - if (ret) - goto err_pm_disable; - + e24_init(e24_dev); + pm_runtime_set_active(e24_dev->dev); + pm_runtime_enable(e24_dev->dev); + if (!pm_runtime_enabled(e24_dev->dev)) { + ret = e24_boot_firmware(e24_dev->dev); + if (ret) + goto err_pm_disable; + } nodeid = ida_simple_get(&e24_nodeid, 0, 0, GFP_KERNEL); if (nodeid < 0) { ret = nodeid; goto err_pm_disable; } + e24_dev->nodeid = nodeid; sprintf(nodename, "eboot%u", nodeid); @@ -1402,8 +1455,9 @@ long e24_init_v0(struct platform_device *pdev) return PTR_ERR(e24_dev); err_free_id: ida_simple_remove(&e24_nodeid, nodeid); + err_pm_disable: - e24_runtime_suspend(e24_dev->dev); + pm_runtime_disable(e24_dev->dev); err_free_map: kfree(e24_dev->address_map.entry); err_free_pool: @@ -1427,10 +1481,11 @@ int e24_deinit(struct platform_device *pdev) { struct e24_device *e24_dev = platform_get_drvdata(pdev); - e24_runtime_suspend(e24_dev->dev); + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(e24_dev->dev)) + e24_runtime_suspend(e24_dev->dev); misc_deregister(&e24_dev->miscdev); - release_firmware(e24_dev->firmware); e24_free_pool(e24_dev->pool); kfree(e24_dev->address_map.entry); ida_simple_remove(&e24_nodeid, e24_dev->nodeid); @@ -1460,12 +1515,18 @@ static int e24_remove(struct platform_device *pdev) return e24_deinit(pdev); } +static const struct dev_pm_ops e24_runtime_pm_ops = { + SET_RUNTIME_PM_OPS(e24_runtime_suspend, + e24_boot_firmware, NULL) +}; + static struct platform_driver e24_driver = { .probe = e24_probe, .remove = e24_remove, .driver = { .name = "e24_boot", .of_match_table = of_match_ptr(e24_of_match), + .pm = &e24_runtime_pm_ops, }, }; diff --git a/drivers/e24/starfive_e24_hw.c b/drivers/e24/starfive_e24_hw.c index 37b7c621d064..94d32d75e4be 100644 --- a/drivers/e24/starfive_e24_hw.c +++ b/drivers/e24/starfive_e24_hw.c @@ -60,8 +60,12 @@ static void disable(void *hw_arg) { struct e24_hw_arg *mail_arg = hw_arg; - reset_control_assert(mail_arg->rst_core); + clk_disable_unprepare(mail_arg->clk_core); + clk_disable_unprepare(mail_arg->clk_dbg); + clk_disable_unprepare(mail_arg->clk_rtc); + pr_debug("e24 disable ...\n"); + } static int enable(void *hw_arg) @@ -69,6 +73,32 @@ static int enable(void *hw_arg) struct e24_hw_arg *mail_arg = hw_arg; int ret = 0; + ret = clk_prepare_enable(mail_arg->clk_core); + if (ret) + return -EAGAIN; + + ret = clk_prepare_enable(mail_arg->clk_dbg); + if (ret) { + clk_disable_unprepare(mail_arg->clk_core); + return -EAGAIN; + } + + ret = clk_prepare_enable(mail_arg->clk_rtc); + if (ret) { + clk_disable_unprepare(mail_arg->clk_core); + clk_disable_unprepare(mail_arg->clk_dbg); + return -EAGAIN; + } + + pr_debug("e24_enable clk ...\n"); + return 0; +} + + +static int init(void *hw_arg) +{ + struct e24_hw_arg *mail_arg = hw_arg; + mail_arg->reg_syscon = syscon_regmap_lookup_by_phandle( mail_arg->e24->dev->of_node, "starfive,stg-syscon"); @@ -101,28 +131,13 @@ static int enable(void *hw_arg) return -ENOMEM; } - ret = clk_prepare_enable(mail_arg->clk_core); - if (ret) - return -EAGAIN; - - ret = clk_prepare_enable(mail_arg->clk_dbg); - if (ret) { - clk_disable_unprepare(mail_arg->clk_core); - return -EAGAIN; - } - - ret = clk_prepare_enable(mail_arg->clk_rtc); - if (ret) { - clk_disable_unprepare(mail_arg->clk_core); - clk_disable_unprepare(mail_arg->clk_dbg); - return -EAGAIN; - } + enable(hw_arg); - pr_debug("e24 enable clk ...\n"); return 0; } static struct e24_hw_ops e24_hw_ops = { + .init = init, .enable = enable, .reset = reset, .halt = halt, diff --git a/drivers/e24/starfive_e24_hw.h b/drivers/e24/starfive_e24_hw.h index e7bd6ae2720e..195c532688bc 100644 --- a/drivers/e24/starfive_e24_hw.h +++ b/drivers/e24/starfive_e24_hw.h @@ -25,6 +25,10 @@ * Hardware-specific operation entry points. */ struct e24_hw_ops { + /* + * Gets the clock for E24. + */ + int (*init)(void *hw_arg); /* * Enable power/clock, but keep the core stalled. */ -- cgit v1.2.3