summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorys <eason.xiong@starfivetech.com>2022-10-28 13:34:15 +0300
committerAndy Hu <andy.hu@starfivetech.com>2024-06-28 13:47:20 +0300
commita87d4c6d8acbf3de07aa303793be0f7b63b68d98 (patch)
tree962d02ac3c52fc360ae24a12b670a8ccc72e7fff
parentd2fffe7bb77dd751f0e2243b2f8e16e1ee588310 (diff)
downloadlinux-a87d4c6d8acbf3de07aa303793be0f7b63b68d98.tar.xz
drive:e24:add runtme pm ops
add runtime pm ops Signed-off-by: ys <eason.xiong@starfivetech.com>
-rw-r--r--drivers/e24/starfive_e24.c121
-rw-r--r--drivers/e24/starfive_e24_hw.c51
-rw-r--r--drivers/e24/starfive_e24_hw.h4
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
@@ -26,6 +26,10 @@
*/
struct e24_hw_ops {
/*
+ * Gets the clock for E24.
+ */
+ int (*init)(void *hw_arg);
+ /*
* Enable power/clock, but keep the core stalled.
*/
int (*enable)(void *hw_arg);