kernel/0064-fix-support-power-managemnt.patch
2024-12-19 16:34:44 -05:00

292 lines
8.5 KiB
Diff

From 89dfcd873fd47cf92ad4c552fcec021e9ccbe50b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9Chuangyifeng=E2=80=9D?=
<huangyifeng@eswincomputing.com>
Date: Thu, 27 Jun 2024 15:08:57 +0800
Subject: [PATCH 064/219] fix:support power managemnt
Changelogs:
1.temporarily disable pwm pm function since it will prevent system
suspending.
2.mailbox driver support for power managment.
3.add cmdline to prevent console suspending
Signed-off-by: huangyifeng <huangyifeng@eswincomputing.com>
---
arch/riscv/configs/win2030_defconfig | 2 +-
drivers/mailbox/eswin-mailbox.c | 115 ++++++++++++++++++++-------
drivers/pwm/pwm-dwc-eswin.c | 2 +-
3 files changed, 89 insertions(+), 30 deletions(-)
diff --git a/arch/riscv/configs/win2030_defconfig b/arch/riscv/configs/win2030_defconfig
index f12568c50271..fd95a7c1c3b5 100644
--- a/arch/riscv/configs/win2030_defconfig
+++ b/arch/riscv/configs/win2030_defconfig
@@ -20,7 +20,7 @@ CONFIG_SOC_VIRT=y
CONFIG_SMP=y
CONFIG_RISCV_SBI_V01=y
# CONFIG_RISCV_BOOT_SPINWAIT is not set
-CONFIG_CMDLINE="earlycon=sbi console=tty1 console=ttyS0,115200n8 clk_ignore_unused cma_pernuma=0x2000000 disable_bypass=false"
+CONFIG_CMDLINE="earlycon=sbi console=tty1 console=ttyS0,115200n8 clk_ignore_unused cma_pernuma=0x2000000 disable_bypass=false no_console_suspend"
CONFIG_CMDLINE_EXTEND=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
diff --git a/drivers/mailbox/eswin-mailbox.c b/drivers/mailbox/eswin-mailbox.c
index 4e9b6b224469..6a2c40e4d45e 100755
--- a/drivers/mailbox/eswin-mailbox.c
+++ b/drivers/mailbox/eswin-mailbox.c
@@ -19,7 +19,6 @@
*
* Authors: HuangYiFeng<huangyifeng@eswincomputing.com>
*/
-
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -31,6 +30,8 @@
#include <linux/mailbox/eswin-mailbox.h>
#include <linux/regmap.h>
#include <linux/reset.h>
+#include <linux/pm_runtime.h>
+
#define ESWIN_MBOX_FIFO_DEPTH 8
@@ -96,7 +97,7 @@ static int eswin_mbox_send_data(struct mbox_chan *chan, void *data)
tmp_data = (u32)(msg->data >> 32) | BIT(31);
regmap_write(mb->map, ESWIN_MBOX_WR_DATA1, tmp_data);
- // 写中断enable bit.
+ // Write interrupt enable bit.
regmap_set_bits(mb->map, ESWIN_MBOX_INT_CTRL, mb->irq_bit);
return 0;
}
@@ -106,12 +107,15 @@ static int eswin_mbox_startup(struct mbox_chan *chan)
struct eswin_mbox *mb = dev_get_drvdata(chan->mbox->dev);
int ret;
+ pm_runtime_get_sync(mb->dev);
+
if (regmap_test_bits(mb->map, ESWIN_MBOX_WR_LOCK, mb->lock_bit)) {
+ pm_runtime_put(mb->dev);
return -1;
}
ret = regmap_set_bits(mb->map, ESWIN_MBOX_WR_LOCK, mb->lock_bit);
-
- /*占用标志位写入成功表示占用成功*/
+
+ /* Successfully write the occupancy flag bit, indicating successful occupancy */
dev_dbg(mb->mbox.dev, "start, ret %d, lock_bit 0x%x\n", ret,
mb->lock_bit);
return ret;
@@ -130,6 +134,7 @@ static void eswin_mbox_shutdown(struct mbox_chan *chan)
if (0 != ret)
dev_err(mb->mbox.dev, "failed to disable mailbox int\n");
+ pm_runtime_put(mb->dev);
return;
}
@@ -184,7 +189,7 @@ static bool eswin_mbox_peek_data(struct mbox_chan *chan)
/*
once the data has been enqueued to mailbox hw FIFO in send_data function,
- we beleive that tx is done
+ we believe that tx is done
*/
static bool eswin_mbox_last_tx_done(struct mbox_chan *chan)
{
@@ -271,7 +276,7 @@ static const struct of_device_id eswin_mbox_of_match[] = {
MODULE_DEVICE_TABLE(of, eswin_mbox_of_match);
static int eswin_mbox_reg_read(void *context, unsigned int reg,
- unsigned int *val)
+ unsigned int *val)
{
struct eswin_mbox *mb = context;
@@ -297,7 +302,7 @@ static int eswin_mbox_rx_reg_read(void *context, unsigned int reg,
return 0;
}
-static int eswin_mbox__rx_reg_write(void *context, unsigned int reg,
+static int eswin_mbox_rx_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct eswin_mbox *mb = context;
@@ -334,7 +339,7 @@ int eswin_mbox_init_regmap(struct eswin_mbox *mb)
.cache_type = REGCACHE_NONE,
.can_sleep = false,
.reg_read = eswin_mbox_rx_reg_read,
- .reg_write = eswin_mbox__rx_reg_write,
+ .reg_write = eswin_mbox_rx_reg_write,
};
/*
@@ -358,6 +363,29 @@ int eswin_mbox_init_regmap(struct eswin_mbox *mb)
return 0;
}
+static int eswin_mbox_prepare_clk(struct device *dev, bool enable)
+{
+ int ret = 0;
+ struct eswin_mbox *mb = dev_get_drvdata(dev);
+
+ if (enable) {
+ ret = clk_prepare_enable(mb->pclk);
+ if (ret) {
+ dev_err(dev, "failed to enable host mailbox pclk: %d\n", ret);
+ return ret;
+ }
+ ret = clk_prepare_enable(mb->pclk_device);
+ if (ret) {
+ dev_err(dev, "failed to enable device mailbox pclk: %d\n", ret);
+ return ret;
+ }
+ } else {
+ clk_disable_unprepare(mb->pclk);
+ clk_disable_unprepare(mb->pclk_device);
+ }
+ return ret;
+}
+
static int eswin_mbox_probe(struct platform_device *pdev)
{
struct eswin_mbox *mb;
@@ -426,13 +454,6 @@ static int eswin_mbox_probe(struct platform_device *pdev)
return ret;
}
- ret = clk_prepare_enable(mb->pclk);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable host mailbox pclk: %d\n",
- ret);
- return ret;
- }
-
mb->pclk_device = devm_clk_get(&pdev->dev, "pclk_mailbox_device");
if (IS_ERR(mb->pclk_device)) {
ret = PTR_ERR(mb->pclk_device);
@@ -440,13 +461,7 @@ static int eswin_mbox_probe(struct platform_device *pdev)
ret);
return ret;
}
-
- ret = clk_prepare_enable(mb->pclk_device);
- if (ret) {
- dev_err(&pdev->dev,
- "failed to enable device mailbox pclk: %d\n", ret);
- return ret;
- }
+ eswin_mbox_prepare_clk(&pdev->dev, true);
mb->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, "rst");
if (IS_ERR(mb->rst))
@@ -465,8 +480,7 @@ static int eswin_mbox_probe(struct platform_device *pdev)
return irq;
ret = devm_request_threaded_irq(&pdev->dev, irq, eswin_mbox_irq,
- eswin_mbox_isr, IRQF_ONESHOT,
- dev_name(&pdev->dev), mb);
+ eswin_mbox_isr, IRQF_ONESHOT, dev_name(&pdev->dev), mb);
if (ret < 0)
return ret;
@@ -480,10 +494,20 @@ static int eswin_mbox_probe(struct platform_device *pdev)
return ret;
spin_lock_init(&mb->rx_lock);
+
+ /* The code below assumes runtime PM to be disabled. */
+ WARN_ON(pm_runtime_enabled(&pdev->dev));
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
ret = devm_mbox_controller_register(&pdev->dev, &mb->mbox);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_disable(&pdev->dev);
dev_err(&pdev->dev, "failed to register mailbox: %d\n", ret);
-
+ }
dev_info(&pdev->dev, "register sucessfully\n");
return ret;
}
@@ -493,21 +517,56 @@ static int eswin_mbox_remove(struct platform_device *pdev)
int ret;
struct eswin_mbox *mb = platform_get_drvdata(pdev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
ret = reset_control_assert(mb->rst);
WARN_ON(ret != 0);
ret = reset_control_assert(mb->rst_device);
WARN_ON(ret != 0);
- clk_disable_unprepare(mb->pclk_device);
- clk_disable_unprepare(mb->pclk);
return 0;
}
+static int eswin_mbox_suspend(struct device *dev)
+{
+ if (!pm_runtime_status_suspended(dev)) {
+ return eswin_mbox_prepare_clk(dev, false);
+ }
+ return 0;
+}
+
+static int eswin_mbox_resume(struct device *dev)
+{
+ if (!pm_runtime_status_suspended(dev)) {
+ eswin_mbox_prepare_clk(dev, true);
+ pm_runtime_mark_last_busy(dev);
+ pm_request_autosuspend(dev);
+ }
+ return 0;
+}
+
+static int eswin_mbox_runtime_suspend(struct device *dev)
+{
+ return eswin_mbox_prepare_clk(dev, false);
+}
+
+static int eswin_mbox_runtime_resume(struct device *dev)
+{
+ return eswin_mbox_prepare_clk(dev, true);
+}
+
+static const struct dev_pm_ops eswin_mbox_dev_pm_ops = {
+ LATE_SYSTEM_SLEEP_PM_OPS(eswin_mbox_suspend, eswin_mbox_resume)
+ RUNTIME_PM_OPS(eswin_mbox_runtime_suspend, eswin_mbox_runtime_resume, NULL)
+};
+
static struct platform_driver eswin_mbox_driver = {
.probe = eswin_mbox_probe,
.remove = eswin_mbox_remove,
.driver = {
.name = "eswin-mailbox",
.of_match_table = of_match_ptr(eswin_mbox_of_match),
+ .pm = pm_ptr(&eswin_mbox_dev_pm_ops),
},
};
diff --git a/drivers/pwm/pwm-dwc-eswin.c b/drivers/pwm/pwm-dwc-eswin.c
index 62c2dfcef719..1873b8351b0c 100644
--- a/drivers/pwm/pwm-dwc-eswin.c
+++ b/drivers/pwm/pwm-dwc-eswin.c
@@ -336,7 +336,7 @@ static struct platform_driver dwc_pwm_driver = {
.remove = dwc_pwm_remove,
.driver = {
.name = "dwc-pwm",
- .pm = &dwc_pwm_pm_ops,
+ //.pm = &dwc_pwm_pm_ops,
.of_match_table = of_match_ptr(dwc_pwm_id_table),
},
};
--
2.47.0